Como posso escalar o número e o desafio de inimigos em uma onda de ataque à medida que o jogo avança?

9

Atualmente, estou fazendo um jogo de defesa em que inimigos aparecerão e atacarão o exército do jogador. É semelhante a um jogo de Tower Defense, exceto que há apenas um nível. Os inimigos continuarão gerando até que, eventualmente, o usuário morra ou ele acumule um exército grande o suficiente para acabar com qualquer inimigo que aparecer instantaneamente (espero que seja desafiador o suficiente para que isso não aconteça).

No momento, estou lutando com como tornar esse jogo progressivamente mais difícil e a probabilidade de um inimigo aparecer basicamente chegando a 100%.

Até agora eu tenho algo parecido com o seguinte

if(Math.random() < 1 - (1/elapsed_time) && spawnTimer <= 0 ){
    spawnEnemy()
    spawnTimer = rand(); // random number between 1 and 3
}

Mas parece muito uniforme para começar. No momento, estou gerando apenas um tipo de inimigo, com a idéia de que inimigos mais difíceis são gerados à medida que o tempo avança também.

Também acho que preciso aleatoriamente um spawnTimerpouco mais e tornar isso mais rápido à medida que o tempo avança, mas simplesmente não consigo entender como minha lógica deve realmente parecer para toda essa seção. Alguém pode ajudar com uma idéia aproximada desse tipo de fórmula?

Atualmente, estou usando javascript para escrever o jogo, mas obviamente é mais sobre o conceito.

TommyBs
fonte
Qual é o tempo decorrido? É o que passou até agora? Com que frequência você chama essa condição?
AturSams 27/01
Olá, sim, desculpe, o tempo decorrido é o tempo decorrido desde o início do jogo e isso é chamado no meu ciclo update () de jogos, que é baseado em window.requestAnimationFrame
TommyBs

Respostas:

3

É provável que a função que você escolheu não seja adequada ao seu objetivo. Primeiro, se você seguir esta rota, uma condição aleatória com falha deve resultar em um atraso antes da próxima vez que você jogar os dados. Além disso, é improvável que manter o cronômetro de reprodução dentro de um intervalo constante seja bom para seu objetivo.

Seja threshum limiar de dificuldade que você considere alto. Usamos isso mais tarde para decidir quando diminuir o ritmo no qual o jogo fica mais difícil.

Seja ratea quantidade de monstros que você deseja que chegue a cada minuto (ou rodada).

Seja GROWTH_RATEa taxa em que a dificuldade aumenta (por enquanto será 0.2).

Digamos que você comece com rate = 10. Agora o jogador matou 5monstros para que você possa aumentar a taxa GROWTH_RATE * 5 = 1.0e o novo rate = 11.

Como implementar uma condição que irá gerar ratemonstros a cada minuto:

Defina o cronômetro de reprodução para um número entre 0.5a taxa de 1.0 multiplied by 60 seconds orronda de 0,25` e a chance de que nenhum monstro seja gerado quando o cronômetro chegar a 0 e o tempo for randomizado novamente.and divided by. Also leave a

Se ratealguma vez chegar, threshvocê precisa desacelerar. Agora, em vez de aumentar ratepor GROWTH_RATE, você pode aumentá-lo 1 / math.sqrt(rate). Dessa forma, o jogador não será destruído instantaneamente no cenário mais difícil.

Você pode redefinir threshpara ficar em torno de 80% do tempo rateem que o jogador perdeu o jogo.

Se você deseja aleatorizar a força do monstro, tenha cuidado com o cronômetro. Por exemplo, se você decidir que player-score(determinada por monstros mortos até agora) será usado para determinar a força máxima de um monstro que poderia gerar, você pode fazer algo como isto: max-monster-strength = player-score / 1000. Em seguida, randomize um floatou doubleentre 0.0para 1.0e multiplique o resultado por si próprio.

float monster_power = Math.random();
monster_power *= monster_power; // Multiply result by itself
    // Makes hard monsters less frequent than weak ones
monster_power *= max_monster_strength;

Agora, quando você seleciona o temporizador aleatoriamente, provavelmente deve levar em consideração o nível de potência. Por exemplo, você pode multiplicar o resultado do timer pela raiz quadrada do próximo poder de monstros.

spawn_timer *= math.sqrt(monster_power);
AturSams
fonte
6

Há muitas opções, duas na sua configuração atual:

  • Tornar os inimigos mais difíceis
  • Gera mais inimigos (com mais frequência ou múltiplos de cada vez)

Mais ainda com recursos adicionais:

  • Os inimigos começam a causar diferentes tipos de dano, e o jogador deve se defender de maneira diferente contra cada um. Por exemplo, ataques à distância, magia etc.
  • Os inimigos começam a se defender contra diferentes tipos de dano. O jogador deve construir vários tipos de dispositivos que causam danos para combater. Por exemplo, o jogador começa com ataques de flechas e ataques de balas de canhão. Um inimigo que tem uma resistência muito alta às flechas aparece, então o jogador deve garantir que equilibrou seus ataques.

Quanto a fazer uma curva de dificuldade, não há realmente uma resposta correta. Vai demorar muito teste e ajustes para acertar. Depende de quanto tempo o jogo deve durar e quão difícil você quer que seja. Sugiro que você use o Excel ou um site como o WolframAlpha e veja que tipo de curva diferentes funções criam. Tente aumentos exponenciais, aumentos lineares, etc. Encontre um que funcione para você.

MichaelHouse
fonte
Obrigado pelas idéias, mas acho que a resposta selecionada é mais o que eu preciso. Mas você definitivamente me dado mais alimento para o pensamento e eu upvoted sua resposta
TommyBs
2

Em vez de ter um número fixo de inimigos (um) gerando com uma probabilidade variável, você pode transformá-lo e ter um número variável de inimigos gerando com uma probabilidade fixa.

static const double SPAWN_CHANCE_ON_DIFFICULTY_1 = 0.01;

for (int i = 0; i < currentDifficulty; i++) {
   if(Math.random() < SPAWN_CHANCE_ON_DIFFICULTY_1 ){
       spawnEnemy()
   }
}

No nível de dificuldade 1, isso terá 1% de chance de gerar um inimigo por carrapato.

No nível de dificuldade 1000, ele gerará até 1000 inimigos, cada um com uma chance separada de 1%. Isso significa que, em média, 10 aparecerão por carrapato, mas também pode ser mais ou menos. Existe a possibilidade de que um número muito diferente de 10 apareça de uma só vez, talvez até todos os 1000. mas esse é um evento muito improvável devido à forma como a probabilidade funciona (compare: Lei dos Grandes Números ).

Quando você adiciona mais inimigos diferentes com comportamentos e estatísticas diferentes, talvez queira que alguns dos inimigos mais difíceis só comecem a gerar dificuldades mais altas e mesmo assim com uma baixa densidade no início. Para fazer isso, você pode adicionar um modificador de dificuldade que é subtraído da dificuldade atual. Dessa forma, o inimigo não irá aparecer antes que o nível de dificuldade seja atingido e mesmo assim apenas com uma chance menor no início:

for (EnemyType enemyType: allEnemyTypes) {
    for (int i = 0; i < currentDifficulty - enemyType.getDifficulty(); i++) {
        if(Math.random() < enemyType.spawnChance() ){
            spawnEnemy(enemyType);
        }
    }
}
Philipp
fonte
11
Isso é estimulante, mas deve ser otimizado antes de ser usado. Por exemplo, você pode usar Math.random () uma vez para decidir quantos inimigos devem aparecer. Se você quiser deixar uma chance menor para uma grande quantidade de inimigos, poderá implementar a "Distribuição Normal" com mais eficiência. stackoverflow.com/questions/2325472/…
AturSams