Wie kann ich die Anzahl und Herausforderung von Feinden in einer Angriffswelle im Verlauf des Spiels skalieren?

9

Ich mache gerade ein Verteidigungsspiel, in dem Feinde erscheinen und die Armee des Spielers angreifen. Es ähnelt einem Tower Defense-Spiel, nur dass es nur ein Level gibt. Die Feinde werden so lange laichen, bis der Benutzer schließlich stirbt oder eine Armee zusammenstellt, die groß genug ist, um jeden Feind auszulöschen, der sofort erscheint (hoffentlich ist es schwierig genug, dass dies nicht passiert).

Was ich im Moment zu kämpfen habe, ist, wie man dieses Spiel zunehmend schwieriger macht und die Wahrscheinlichkeit, dass ein Feind laicht, letztendlich 100% erreicht.

Bisher habe ich etwas Ähnliches wie das Folgende

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

Aber es scheint zunächst zu einheitlich. Im Moment spawne ich nur eine Art von Feind. Die Idee ist, dass im Laufe der Zeit auch härtere Feinde erzeugt werden.

Ich denke auch, dass ich meine spawnTimeretwas mehr randomisieren und das mit der Zeit schneller machen muss, aber ich kann einfach nicht sehen, wie meine Logik für diesen ganzen Abschnitt wirklich aussehen sollte. Kann jemand mit einer groben Vorstellung von dieser Art von Formel helfen?

Ich benutze derzeit Javascript, um das Spiel zu schreiben, aber offensichtlich geht es mehr um das Konzept.

TommyBs
quelle
Was ist die verstrichene Zeit? Ist es das, was bis jetzt vergangen ist? Wie oft nennen Sie diesen Zustand?
AturSams
Hallo, ja, tut mir leid, die verstrichene Zeit ist die Zeit, die seit dem Start des Spiels vergangen ist, und dies wird in meinem Spiel-Update () -Zyklus aufgerufen, der auf window.requestAnimationFrame
TommyBs

Antworten:

3

Die von Ihnen gewählte Funktion ist wahrscheinlich nicht für Ihren Zweck geeignet. Wenn Sie diesen Weg gehen, sollte eine fehlgeschlagene zufällige Bedingung zu einer Verzögerung führen, bevor Sie das nächste Mal würfeln. Es ist auch unwahrscheinlich, dass es für Ihr Ziel gut ist, den Spawn-Timer in einem konstanten Bereich zu halten.

Sei thresheine Schwierigkeitsschwelle, die du für hoch hältst. Wir verwenden das später, um zu entscheiden, wann das Tempo, mit dem das Spiel schwieriger wird, verlangsamt werden soll.

Sei ratedie Anzahl der Monster, die in jeder Minute (oder Runde) kommen sollen.

Sei GROWTH_RATEdie Geschwindigkeit, mit der sich der Schwierigkeitsgrad erhöht (vorerst wird es so sein 0.2).

Angenommen, Sie beginnen mit rate = 10. Jetzt hat der Spieler 5Monster getötet, damit du die Rate nach GROWTH_RATE * 5 = 1.0und nach erhöhen kannst rate = 11.

So implementieren Sie eine Bedingung, die ratejede Minute Monster erzeugt :

Set Spawn - Timer auf eine Zahl zwischen 0.5zu Rundzeitrate1.0 multiplied by 60 seconds or 0.25` Chance , dass kein Monster hervorgebracht wird , wenn der Timer 0 erreicht und die Zeit wieder randomisiert.and divided by. Also leave a

Wenn Sie ratejemals erreichen thresh, müssen Sie langsamer fahren. Anstatt nun zu erhöhen ratedurch GROWTH_RATE, können Sie es durch erhöhen 1 / math.sqrt(rate). Auf diese Weise wird der Spieler in der schwierigeren Umgebung nicht sofort zerstört.

Sie können threshauf ungefähr 80% des Wertes zurücksetzen , ratebei dem der Spieler das Spiel verloren hat.

Wenn du die Stärke des Monsters zufällig bestimmen willst, sei vorsichtig mit dem Timer. Wenn Sie beispielsweise entscheiden, dass player-score(bestimmt durch bisher getötete Monster) die maximale Stärke eines Monsters bestimmt wird, das erscheinen könnte, können Sie Folgendes tun : max-monster-strength = player-score / 1000. Dann zufällig ein floatoder doublezwischen 0.0auf 1.0und multiplizieren Sie das Ergebnis für sich.

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;

Wenn Sie nun den Timer zufällig auswählen, sollten Sie wahrscheinlich die Leistungsstufe berücksichtigen. Zum Beispiel könnten Sie das Timer-Ergebnis mit der Quadratwurzel der nächsten Monster-Kraft multiplizieren.

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

Es gibt viele Optionen, zwei mit Ihrem aktuellen Setup:

  • Machen Sie Feinde schwerer
  • Bringe mehr Feinde hervor (entweder öfter oder mehrere gleichzeitig)

Dann mehr mit zusätzlichen Funktionen:

  • Feinde verursachen unterschiedliche Arten von Schaden und der Spieler muss sich gegen jeden unterschiedlich verteidigen. Zum Beispiel Fernkampfangriffe, Magie usw.
  • Feinde beginnen sich gegen verschiedene Arten von Schaden zu verteidigen. Der Spieler muss mehrere Arten von Schaden verursachenden Geräten bauen, um zu kontern. Zum Beispiel beginnt der Spieler mit Pfeilangriffen und Kanonenkugelangriffen. Ein Feind, der einen sehr hohen Widerstand gegen Pfeile hat, spawnt, daher muss der Spieler sicherstellen, dass er seine Angriffe ausgeglichen hat.

Für die Erstellung einer Schwierigkeitskurve gibt es wirklich keine richtige Antwort. Es wird eine Menge Spieltests und Optimierungen erfordern, um es richtig zu machen. Es hängt davon ab, wie lange das Spiel dauern soll und wie schwierig es sein soll. Ich schlage vor, Sie verwenden Excel oder eine Site wie WolframAlpha und sehen, welche Art von Kurve verschiedene Funktionen erstellen. Versuchen Sie es mit exponentiellen Erhöhungen, linearen Erhöhungen usw. Finden Sie eine, die für Sie funktioniert.

MichaelHouse
quelle
Vielen Dank für die Ideen, aber ich denke, die ausgewählte Antwort ist mehr, was ich brauche. Aber Sie haben mir definitiv mehr Denkanstöße gegeben und ich habe Ihre Antwort
positiv
2

Anstatt eine feste Anzahl von Feinden (einen) mit variabler Wahrscheinlichkeit erscheinen zu lassen, könnten Sie es umdrehen und eine variable Anzahl von Feinden mit einer festen Wahrscheinlichkeit erscheinen lassen.

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()
   }
}

Auf Schwierigkeitsgrad 1 hat dies eine Chance von 1%, einen Gegner pro Tick hervorzubringen.

Im Schwierigkeitsgrad 1000 werden bis zu 1000 Feinde mit einer separaten Chance von 1% erzeugt. Dies bedeutet, dass durchschnittlich 10 pro Tick erscheinen, aber es kann auch mehr oder weniger sein. Es besteht die Möglichkeit, dass eine Zahl, die sich stark von 10 unterscheidet, sofort erscheint, vielleicht sogar alle 1000. Dies ist jedoch aufgrund der Funktionsweise der Wahrscheinlichkeit ein sehr unwahrscheinliches Ereignis (vgl. Gesetz der großen Zahlen ).

Wenn Sie mehr verschiedene Feinde mit unterschiedlichen Verhaltensweisen und Statistiken hinzufügen, möchten Sie vielleicht, dass einige der härteren Feinde erst auf höheren Schwierigkeitsgraden und selbst dann mit einer geringen Dichte anfangen zu laichen. Dazu können Sie einen Schwierigkeitsgrad-Modifikator hinzufügen, der vom aktuellen Schwierigkeitsgrad abgezogen wird. Auf diese Weise wird der Feind nicht erscheinen, bevor dieser Schwierigkeitsgrad erreicht ist, und selbst dann zunächst nur mit einer geringeren Chance:

for (EnemyType enemyType: allEnemyTypes) {
    for (int i = 0; i < currentDifficulty - enemyType.getDifficulty(); i++) {
        if(Math.random() < enemyType.spawnChance() ){
            spawnEnemy(enemyType);
        }
    }
}
Philipp
quelle
1
Dies ist anregend, sollte jedoch vor der Verwendung optimiert werden. Zum Beispiel könnten Sie Math.random () einmal verwenden, um zu entscheiden, wie viele Feinde erzeugt werden sollen. Wenn Sie eine kleinere Chance für eine große Anzahl von Feinden lassen möchten, können Sie die "Normalverteilung" effizienter implementieren. stackoverflow.com/questions/2325472/…
AturSams