Idéias para o algoritmo de dano de ataque (linguagem irrelevante)

8

Estou trabalhando em um jogo e preciso de idéias para o dano que será causado ao inimigo quando o seu jogador atacar. A quantidade total de pontos de vida que o inimigo tem é chamada enemyHealthe tem um valor de 1000. Você começa com uma arma que causa 40 pontos de dano (pode ser alterado.) O jogador tem um status de ataque que você pode aumentar, chamado playerAttack. Esse valor começa em 1 e tem um possível valor máximo de 100 depois que você aumenta o nível várias vezes e o torna mais longe no jogo. A quantidade de dano que a arma causa é cortada e seca e subtrai 40 pontos do total de 1000 pontos de vida toda vez que o inimigo é atingido. Mas o que playerAttackfaz é adicionar a esse valor com uma porcentagem. Aqui está o algoritmo que tenho agora. (Eu tirei todas as GUI, classes, etc. e dei nomes variáveis ​​para a frente)

double totalDamage = weaponDamage + (weaponDamage*(playerAttack*.05))
enemyHealth -= (int)totalDamage;

Isso pareceu funcionar muito bem na maior parte. Então eu testei alguns valores ...

//enemyHealth ALWAYS starts at 1000
weaponDamage = 50;
playerAttack = 30;

Se eu definir esses valores, a quantidade de dano causado no inimigo é 125. Parecia um bom número, então eu queria ver o que aconteceria se o ataque dos jogadores fosse maximizado, mas com a arma inicial mais fraca.

weaponDamage = 50;
playerAttack = 100;

o totalDamage acaba sendo 300, o que mataria um inimigo em apenas alguns acertos. Mesmo com seu ataque tão alto, eu não gostaria que a arma mais fraca fosse capaz de matar o inimigo tão rápido. Pensei em adicionar defesa, mas sinto que o jogo perderá consistência e se desequilibrará a longo prazo. Possivelmente, um algoritmo bem projetado para um modificador de redução de arma funcionaria para armas de nível inferior ou algo assim. Só preciso de uma pausa para tentar descobrir a melhor maneira de fazer isso, e talvez alguém que tenha experiência com jogos e mantenha o nivelamento consistente possa me dar algumas idéias / dicas.

Dillon
fonte
2
Acho que precisamos de um pouco mais de informação. É fácil nivelar sua playerAttackestatística para 100? Considerando que este é o valor máximo, não seria apropriado matar o inimigo em alguns acertos? (É o inimigo algo 1000 HP você veria no início do jogo Um inimigo padrão chefe???)
Lee

Respostas:

14

A resposta fornecida por Grzegorz Sławecki já é boa, mas eu queria explicar a lógica por trás do método dele e fornecer as ferramentas para adaptar as soluções às suas necessidades de jogo.

Os parâmetros da presente problema é o nível de ataque do jogador um , dano da arma W , os danos infligidos total num ataque d , saúde do inimigo H e o número mínimo de visitas necessárias para matar o inimigo, chamemos-lhe n .

Se você quer que o jogador mate em n acertos, o dano total d deve ser tal que

(n-1) .d <H ≤ nd    ou em outras palavras, n = ceil (H / d) .

d depende de dano da arma w e no nível de ataque do jogador um e podemos esperar armas para obter melhor como o nível aumenta, então vamos escrever d (a) e w (a) em vez de simplesmente d e w . Os inimigos que o jogador enfrenta também devem ficar mais difíceis, então, novamente, H (a) . Todas essas são funções crescentes de a e você deseja que elas satisfaçam as inequações acima. As incógnitas do problema são funções. Você define um como uma restrição e encontra os outros. Você tem graus de liberdade, o que é uma coisa boa.

Se eu entendi bem sua pergunta, você tem uma jogabilidade precisa em mente, e essa jogabilidade é representada aqui principalmente pelo número de acertos necessários para matar o inimigo, n (a) . Portanto, defina n (a) dependendo da jogabilidade que você imagina para o jogo e encontre o restante das variáveis ​​do problema . É isso que você sempre deve fazer, porque, como mostra sua pergunta, sua primeira tentativa foi tentar um algoritmo que você pensou que poderia fazer e depois percebeu que resultava em uma jogabilidade indesejada.

Vamos supor, por exemplo, que você queira que o jogador bata mais e mais vezes à medida que avança no jogo. Você também deseja que, à medida que o número necessário de acertos aumente, ele aumente cada vez menos, para que o jogador gaste uma parte mais longa do jogo batendo 5 vezes e 2 vezes. Aqui está a aparência de n (a) :

o n desejado (a)

A função usada é n (a) = ceil (2 / 3.sqrt (a)) .

Queremos que H (a) / d (a) permaneça dentro dos intervalos de valores que fazem n (a) ter o valor desejado e, como n (a) = teto (H (a) / d (a)) , esses intervalos são os seguintes retângulos:

n (a) e n (a) -1

e H (a) / d (a) podem naturalmente ser configurados para 2 / 3.sqrt (a), de modo a obter o gráfico a seguir, com a curva vermelha sendo H (a) / d (a) :

n (a), n (a) -1 e H (a) / d (a)

Observação: podemos facilmente encontrar H (a) / d (a) aqui porque sabemos a função de que n (a) é o teto, mas se nossa especificação para n fosse menos agradável, teríamos que fazer nosso próprio ajuste função usando vários truques. Nem todos os problemas são bons!

Portanto, queremos que H (a) / d (a) se assemelhe a uma função de raiz quadrada personalizada e sabemos que H e d devem estar aumentando as funções. As soluções são abundantes. Por exemplo,

H (a) = a. 2 / 3.sqrt (a),    e    d (a) = a

Uma primeira solução para H e d

Mas gostaríamos que o dano e o HP do inimigo aumentassem muito, para que haja números grandes e impressionantes no final do jogo, apenas por estilo, por isso, definimos

H (a) = a². 20 / 3.sqrt (a),    e    d (a) = 10.a²

Uma solução melhor para H e d

A questão toda, e a melhor parte, é esta: você sabe que suas soluções para o problema ( H (a) e d (a) ) obedecem às especificações ( n (a) ), para obter o mesmo n (a) , mas você tem liberdade. Você conhece exatamente a liberdade que tem e pode usá-lo para personalizar a experiência. Você deve sempre tentar se dar essa liberdade, satisfazendo suas necessidades mais importantes, sempre que possível.

Agora que escolhemos o dano de um golpe d (a) e como d (a) depende do dano da arma w (a) , podemos usar d (a) como nossa especificação e tentar encontrar um w (a ) que nos fornece esse d (a) . Os princípios são os mesmos, o problema é diferente: queremos que o jogador cause mais dano à medida que seu nível aumenta, mesmo com a arma permanecendo a mesma, e também queremos que o dano aumente quando a arma sozinha melhorar e o nível permanecer. o mesmo.

Mas que importância cada fator deve ter? Suponha que queremos que o nível seja mais importante que as armas: uma parte maior das variações de d (a) = a² deve ser independente de w (a) , por exemplo, com

w (a) = 22.sqrt (a)    e, portanto,    d (a) = (22.sqrt (a)). (10 / 22.a.sqrt (a)) = w (a). (10 / 22.a.sqrt (a))

Obtemos o gráfico a seguir para w (a) ...

w (a)

... e ainda o mesmo d (a) , porque nós novamente encontrou uma solução que obedeceu a especificação , aqui de d (a) , e nós temos as propriedades citadas acima, com w e um contribuindo para o dano (suponha que nós olhamos d em função de a e w : então, se a fosse fixo e tivéssemos w variado na equação d (a, w) = a / 30.w , d ainda seria uma função crescente de w , e o mesmo é verdadeiro se você fixa w e faz uma variação).

Este w (a) pode fornecer o valor a ser exibido na descrição do jogo na arma: obteríamos "Dano na Arma: 220" com a melhor arma do jogo, por exemplo.

Poderíamos ter usado uma especificação completamente diferente para nossa jogabilidade e, portanto, para n (a) , por exemplo, uma que faz o número de acertos necessários aumentar rapidamente à medida que o jogo avança e depois atinge o platô, e as soluções resultantes seriam diferentes.

jrsala
fonte
Isso combina uma sólida compreensão da matemática com a jogabilidade como ponto de partida. Uma excelente resposta.
Marcks Thomas
11
@MarcksThomas Bem, obrigado! Eu gostaria que mais pessoas definissem suas necessidades claramente e construíssem seus jogos a partir daí. Veríamos jogos de qualidade mais completos e concluídos dessa maneira.
jrsala
Sim, concordo que esta é a resposta perfeita. Eu li isso com prazer :)
Grzegorz Sławecki
11
Fantástico! Eu gostaria que esse tipo de matemática fosse uma parte mais regular da literatura de design de sistemas. (Talvez eu devesse escrever o meu ensaio sobre escudos danos vs. algum dia ...)
Steven Stadnicki
Ótima resposta, mas por que você deve usar variáveis ​​de um caractere em suas equações? Quantas vezes pergunto: "O que asignifica de novo?" e rolar para cima?
Daniel Kaplan
9

Eu recomendo que você projete seu jogo de outra direção: primeiro pense em como você deseja que ele jogue (em termos de experiência de jogo, e não em números) e, em seguida, projete as fórmulas e os intervalos de números para obter esse resultado.

Seu objetivo no jogo é levar um certo número de acertos para matar um inimigo. Quantos acessos dependem de três variáveis:

  • nível de poder do inimigo
  • nível de poder do personagem
  • nível de poder da arma

Primeiro, você deve criar uma tabela de todas as combinações possíveis dessas três variáveis, de nível baixo, médio ou alto (ainda não há números concretos, apenas "baixo", "médio" ou "alto") e quantas ocorrências deseja necessário para essas combinações.

Em seguida, tente encontrar uma fórmula e intervalos de valores que se aproximem melhor dos seus valores desejados.

Philipp
fonte
7

A maneira mais fácil é aumentar o dano da arma exponencialmente entre os níveis da arma.

No entanto, o que importa é que você também deve definir como o HP dos inimigos cresce quando eles estão ficando mais fortes. Então, quando você é muito forte, você deve matar inimigos fáceis com apenas alguns acertos, mas aqueles no seu nível devem ser relativamente mais difíceis de matar do que os inimigos que estavam no seu nível no início. Então, eu o projetaria para parecer um pouco abaixo:

level   weapon  enemy   attack  total   hits needed
        dmg     hp      factor  dmg     to kill
======================================================
1       1       2       5       1.25    1.6
2       4       16      10      6       2.666666667
3       9       54      15      15.75   3.428571429
4       16      128     20      32      4
5       25      250     25      56.25   4.444444444
6       36      432     30      90      4.8
7       49      686     35      134.75  5.090909091
8       64      1024    40      192     5.333333333
9       81      1458    45      263.25  5.538461538
10      100     2000    50      350     5.714285714
11      121     2662    55      453.75  5.866666667
12      144     3456    60      576     6
13      169     4394    65      718.25  6.117647059
14      196     5488    70      882     6.222222222
15      225     6750    75      1068.75 6.315789474
16      256     8192    80      128     6.4
17      289     9826    85      1517.25 6.476190476
18      324     11664   90      1782    6.545454545
19      361     13718   95      2075.75 6.608695652
20      400     16000   100     2400    6.666666667
Onde:
1. dmg total é calculado usando sua fórmula
2. arma dmg = nível * nível (crescimento exponencial)
3. inimigo hp = 2 * nível * nível * nível (crescimento exponencial)
4. fator de ataque = 5 * nível
5. acertos necessários descreve quantos acertos são necessários no nível x e usando arma no nível x, para matar um inimigo no nível x

Ajustei esses fatores constantes nas fórmulas apenas para alcançar resultados que eu acho aceitáveis, mas o importante é onde você deseja crescimento linear e onde deseja exponencial.

Você também deve notar que, por exemplo, matar o inimigo lvl 20 com 100 ataques e a arma lvl1, que totaliza 6 dmg, levará muito tempo. Se levar muito na sua opinião, brinque com constantes.

Grzegorz Sławecki
fonte
O que significa "fator de ataque"?
Daniel Kaplan
0

Eu acho que o método de artesanato de guerra é um dos melhores. As estatísticas básicas dos jogadores têm um baixo impacto no dano total, com a maioria do modificador de dano vindo das estatísticas de bônus nas artes. Isso facilita muito a expansão e o equilíbrio do jogo à medida que o tempo passa.

ProtoJazz
fonte