Wie funktionieren Kugeln in Videospielen?


64

Ich bin auf diese Frage gestoßen, als ich ein Videospiel in C # entwarf.

Wenn wir Spiele wie Battlefield oder Call of Duty in Betracht ziehen , fliegen Hunderte oder sogar Tausende von Kugeln gleichzeitig. Ereignisse werden ständig ausgelöst und, soweit ich weiß, verbraucht dies viel Rechenleistung ... oder doch? Ich möchte wissen, wie verschiedene Spieleentwickler Aufzählungszeichen (2D und 3D) verwalten und welche Methode jeweils am effizientesten ist.

Ich habe die Frage gelesen, wie Kugeln in Videospielen simuliert werden. Aber es geht nicht darum, wie Aufzählungszeichen aus der Sicht des Programmdesigns funktionieren.

Ich hatte ein paar Ideen, aber jede hat ihre Nachteile:


Die effizienteste Methode, die ich mir vorstellen kann (für 2D-Spiele):

Angenommen, ich würde eine Klasse namens Bullet erstellen, und so lange der Benutzer eine Schaltfläche gedrückt hält, würde alle 0,01 Sekunden ein Bullet-Objekt erstellt. Diese Kugel hat:

  • 1 Geschwindigkeit

  • 2 Startposition, von der aus aufgenommen wird

  • 3 Sprite-Textur

  • 4 Ein On-Hit-Effekt

Da die Kugel eine eigene Klasse sein würde, könnte sie das Zeichnen, Bewegen und Zuhören von Aktionen selbst verwalten.

Wäre es nicht schwierig für den Prozessor, Tausende dieser Objekte zu verarbeiten, die instanziiert und dann zerstört werden (wenn ein On-Hit-Effekt ausgelöst wird)? RAM-Speicher?


Effiziente Methode für 3D-Spiele - Ein weiterer Gedanke, den ich hatte, war:

Sagen wir, ich erstelle eine Waffenklasse. Diese Waffe hat verschiedene Eigenschaften, von denen einige:

  • 1 Ermitteln Sie, wohin die Waffe zielt, und bestimmen Sie, ob sie auf ein Ziel gerichtet ist

  • 2 Lösen Sie eine Animation des Waffenschießens aus

  • 3 Verfügt über eine doDamage () -Methode, die angibt, auf was auch immer die Waffe gerichtet ist, um die Gesundheit zu subtrahieren

  • 4 Benachrichtigt eine Aufzählungszeichen-Animationsklasse, wenn die Schaltfläche gedrückt wird

Ich könnte dann eine statische Klasse, z. B. BulletAnimation, erstellen, die eine Benachrichtigung darüber erhält, wo sich die Waffe befindet, auf die sie gerichtet ist (für das Ziel der Kugel), und Informationen zu einem geeigneten Sprite und einer Geschwindigkeit, die für die Kugel verwendet werden können . Diese Klasse zeichnet dann Sprites (auf einem neuen Thread, vielleicht idk) basierend auf beiden Positionen und dem gewünschten Sprite, um eine Kugel zu simulieren, die von einer Waffe abgefeuert wird.


Letzteres scheint viel schwieriger zu programmieren zu sein, und würde es nicht eine Menge Rechenleistung erfordern, die Statik ständig aufzurufen, um dies für Tausende von Aufzählungszeichen gleichzeitig zu tun? Ständige Aktualisierungen von Start- und Endpositionen wären ebenfalls schwierig.

Meine Frage ist, wie Spieleentwickler es am effizientesten machen. Wechselt diese Methode von 2D- zu 3D-Spielen?


16
Beachten Sie, dass die meisten Spiele auch heute noch nicht den Flug von Kugeln simulieren. Für alles, was als "schnell genug" eingestuft wird, wird stattdessen ein einfacher Treffer-Scan durchgeführt. Grundsätzlich wird davon ausgegangen, dass der Aufprall gleichzeitig mit dem Drücken des Auslösers erfolgt. Auf jeden Fall ist "Hunderte oder Tausende von Kugeln" nicht wirklich eine große Menge - das ist etwas, was Spiele seit sehr frühen Konsolen (verschiedene Bullet-Hell-Spiele) hatten, die tausende Male weniger leistungsfähig sind als die heutigen Maschinen. Sie müssen nur sicherstellen, dass Sie nur so wenig Arbeit wie möglich pro Kugel
erledigen

42
Kugeln arbeiten normalerweise über pew-pew-pewTechnologie :)
MonkeyZeus

5
Es fliegen niemals Hunderte oder Tausende von Kugeln gleichzeitig umher. Es gibt keine Waffe, die sie so schnell abfeuert. Sogar die mächtige Phalanx erreicht 75 Kugeln pro Sekunde. Basierend auf der bei Wikipedia angegebenen "effektiven Schussreichweite" fliegen die Kugeln höchstens 3 Sekunden lang, sodass eine Phalanx 225 Kugeln gleichzeitig in die Luft werfen kann. Ein M16 erreicht eine Höchstgeschwindigkeit von ca. 12 Schuss / Sekunde und kann diese Geschwindigkeit nicht halten (maximal 0,25 Schuss / Sekunde für Dauerfeuer). Es gibt nur nicht so viele Kanonen, die gleichzeitig schießen!
Cort Ammon

3
Um dies zu verdeutlichen, ist es niemals gut, Objekte zu individuellen Klassen zu machen, wenn sie so einfach sind. Es ist weitaus besser, eine bulletField-Instanz für jede Art von Aufzählungszeichen zu haben. Der geringe Mehraufwand an Codelänge und so weiter erspart Ihnen ein zusätzliches 4-Byte-Wort pro Aufzählungszeichen (wenn type eine Ganzzahl ist). Außerdem kann ein Objekt problemlos eine Liste scannen.
Die große Ente

4
@Cort - das ist wahr, vorausgesetzt, es gibt nur eine Schusswaffe im Spielfeld. Das OP erwähnte Spiele wie Battlefield und CoD, in denen Dutzende von Spielern gleichzeitig automatische Waffen abfeuern könnten. Es ist nicht unvernünftig, dass es eine lächerliche Zahl gibt, wenn jede Runde tatsächlich physisch im Weltraum abgerechnet wurde.
Jesse Williams

Antworten:


78

Ich kann mit Sicherheit nachvollziehen, warum Sie der Meinung sind, dass es schwierig ist, diese zu simulieren, aber es gibt genug Einschränkungen für Kugeln (eigentlich alle Projektile), um sie einfacher zu machen.

  1. Sie werden im Allgemeinen als ein einzelner Punkt simuliert, anstatt als etwas mit Volumen. Dies erleichtert die Kollisionserkennung erheblich, da ich jetzt nur noch Kollisionen mit sehr einfachen Oberflächen durchführen muss, z. B. einer Linie gegen einen Kreis.

  2. Wir wissen, wie sie sich bewegen werden, daher brauchen wir nicht viele Informationen, um sie zu speichern oder zu berechnen. Ihre Liste war einigermaßen genau. Im Allgemeinen haben wir noch ein paar Dinge damit zu tun, z. B. wer die Kugel abgeschossen hat und welche Art sie hat.

  3. Da alle Projektile sehr ähnlich sind, können wir sie vorab zuweisen, um den Aufwand für die dynamische Erstellung zu vermeiden. Ich kann ein Array von 1000 Projektilen zuweisen, und jetzt kann mit nur einem Index auf sie zugegriffen werden, und sie sind alle sequentiell im Speicher, sodass ihre Verarbeitung schnell vonstatten geht.

  4. Sie haben eine feste Lebensdauer / Reichweite, sodass ich alte Aufzählungszeichen verfallen lassen und den Speicher sehr schnell in neue Aufzählungszeichen umwandeln kann.

  5. Sobald sie etwas getroffen haben, kann ich sie auch auslaufen lassen, sodass sie eine begrenzte Lebensdauer haben.

  6. Da wir wissen, wann sie erstellt wurden, wenn wir neue benötigen und wir keine freien in unserer vorab zugewiesenen Liste haben, kann ich einfach die ältesten nehmen und sie recyceln, und die Leute werden es nicht bemerken, wenn die Kugeln etwas früher ablaufen .

  7. Sie werden (normalerweise) als Sprites oder als Low-Poly-Modelle gerendert und beanspruchen nur sehr wenig Platz auf dem Bildschirm, sodass sie schnell gerendert werden können.

Unter Berücksichtigung all dieser Faktoren sind Kugeln in der Regel relativ billig. Wenn unser Budget jemals durch Aufzählungszeichen aufgebraucht und gerendert wurde, haben wir es im Allgemeinen neu gestaltet, um die Anzahl der Schüsse zu begrenzen, die Sie gleichzeitig abgeben können (dies wird in vielen alten Arcade-Spielen zu sehen sein). Verwenden Sie Strahlwaffen, die sich sofort bewegen oder verlangsamen Sie die Feuerrate, um sicherzustellen, dass wir innerhalb des Budgets bleiben.


12
Ich muss mit 5) nicht einverstanden sein, was das Ganze in modernen Spielen tatsächlich nur kompliziert macht. Bei früheren Schützen war dies akzeptabel, heutzutage können Spieler sogar mit Nachnahme durch Holzwände schießen. 6) wäre für jedes Wettbewerbssystem inakzeptabel, obwohl dies ein seltenes Problem wäre.
SBoss

17
@SBoss dann umformulieren: "Sobald sie etwas treffen, das sie nicht durchdringen können, kann ich sie auch auslaufen lassen, damit sie eine endliche Lebensdauer haben." Und für 6 Sie einen schlimmsten Fall bekommen können durch die maximale Feuerrate pro Zeichen Capping und dann eine Reihe von Länge zu haltennum_characters * max_bullets_per_character
Ratsche Freak

14
@SBoss Ich denke # 6 ist mehr für zB. Top-Down-Weltraumspiele, bei denen sich eine sich langsam bewegende Kugel außerhalb des Bildschirms weit bewegen kann, bevor sie etwas trifft / verschwindet. Offensichtlich ist dies kein Problem bei CoD-Spielen, bei denen sich Kugeln schnell bewegen und schnell die Grenzen der Welt erreichen.
BlueRaja - Danny Pflughoeft

1
Die überwiegende Mehrheit der Spiele modelliert überhaupt KEINE Kugeln (externe Ballistik). Die meisten Spiele verwenden eine Technik namens "Hit-Scanning".
Aron

45

Eine der effizientesten Methoden zur Implementierung von Aufzählungszeichen ist wahrscheinlich die Verwendung des so genannten Treffer-Scans . Die Implementierung ist recht einfach: Wenn Sie feuern, überprüfen Sie, auf was die Waffe abzielt (verwenden Sie möglicherweise einen Strahl, um das nächste Objekt zu finden), und treffen Sie es dann, um Schaden zu verursachen. Wenn Sie den Eindruck erwecken möchten, dass eine tatsächliche, sich schnell bewegende, unsichtbare Kugel abgefeuert wurde, können Sie sie vortäuschen, indem Sie eine von der Entfernung abhängige Verzögerung hinzufügen, bevor Sie Schaden anrichten.

Bei diesem Ansatz wird im Wesentlichen davon ausgegangen, dass das abgefeuerte Projektil eine unendliche Geschwindigkeit hat und typischerweise für Waffentypen wie Laser und Partikelstrahlen / Kanonen und möglicherweise einige Formen von Scharfschützengewehren verwendet wird .

Der nächste Ansatz wäre, die abgefeuerte Kugel als Projektil zu modellieren, das als eigene Entität / Objekt modelliert wird, das einer Kollision unterliegt, und möglicherweise Schwerkraft und / oder Luftwiderstand, die seine Richtung und Geschwindigkeit verändern. Es ist aufgrund der zusätzlichen physikalischen Gleichungen komplexer als der Treffer-Scan-Ansatz und ressourcenintensiver, da es sich um ein tatsächliches Aufzählungsobjekt handelt, kann jedoch realistischere Aufzählungszeichen liefern.

Beim Verwalten von Kollisionen zwischen Geschossen auf Projektilbasis und anderen Objekten im Spiel kann die Kollisionserkennung erheblich vereinfacht werden, indem Sie Ihre Objekte in Quad- oder Octrees sortieren . Octrees werden hauptsächlich in 3D-Spielen verwendet, während Quadtrees in 2D- oder 3D-Spielen verwendet werden können. Die Verwendung eines dieser Bäume hat den Vorteil, dass Sie die Anzahl möglicher Kollisionsprüfungen erheblich reduzieren können. Wenn Sie beispielsweise 20 Objekte in der Ebene aktiv haben, ohne einen dieser Bäume zu verwenden, müssen Sie alle 20 auf eine Kollision mit der Kugel prüfen. Teilen Sie die 20 Objekte auf die Blätter (Endknoten) des Baums auf, und reduzieren Sie die Anzahl der Überprüfungen auf die Anzahl der Entitäten, die sich im selben Blatt wie das Aufzählungszeichen befinden.

Für diese Ansätze - Trefferabtastung und Projektil - können beide in 2D- oder 3D-Spielen frei verwendet werden. Es hängt mehr davon ab, was die Waffe ist und wie der Schöpfer entschieden hat, dass die Waffe funktionieren soll.


Die Informationen über das Entwurfsmuster, Hitscan und Quad / Octrees helfen wirklich. Danke auch für die Info!
Eric

8
Wenn Sie keinen Treffer-Scan verklagen, sondern die Projektile simulieren, können sie sich durch dünne Objekte verbiegen, weil sie sich so schnell bewegen. Denken Sie in diesem Fall daran, dass alles in Spielen falsch ist. Obwohl eine Kugel nur wenige Zentimeter lang ist, können Sie die Kollisionserkennung so durchführen, als ob die Kugel einen Meter lang wäre. Auf diese Weise können Sie immer noch schöne Flugsimulationen durchführen, ohne sich zu viele Gedanken über Kugeln machen zu müssen, die sich durch Objekte verziehen, ohne sie zu treffen :).
Roy T.

2
Gibt es Spiele, bei denen die Physik von Kugeln (im Gegensatz zu beispielsweise Kanonenhülsen) Dinge wie die Schwerkraft (Bullet Drop) oder den Luftwiderstand berücksichtigt? (Das heißt, Spiele neben Spezialspielen, bei denen der Fokus auf Präzisionsschießen oder so ähnlichem liegt: FPS usw.) Ich bin kein Spieler, aber ich bin überrascht, dass dieses Maß an Wiedergabetreue (auch manchmal) erforderlich ist.
Davidbak

3
@davidbak: Es hängt stark von der typischen Begegnung im Spiel und dem Realismus ab, der vom Spielgenre erwartet wird. Wenn Sie hauptsächlich (nur?) Nahkämpfe austragen, ist dieses Maß an Wiedergabetreue in der Tat nicht erforderlich. Wenn jedoch die Option für Fernkämpfe besteht (z. B. Scharfschützen oder Bogenschützen in einer RPG-ähnlichen Umgebung), ist heutzutage mit einer Schwerkrafteinwirkung auf Raketen zu rechnen. Wenn Sie Ihren Raketenwerfer nach oben richten, würden Sie trotzdem erwarten, dass die Rakete landet und irgendwo explodiert, nicht wahr? Dennoch sind die Flugbahnen nicht immer aus der realen Physik berechnet, sondern nur eine Annäherung (aus Leistungsgründen)
hoffmale

1
@davidbak Battlefield, da Bad Company 2 einen Bullet Drop hatte. Sowohl für Gewehre, Pistolen, Panzergranaten, Raketen, alles. Battlefield 3 ist in Origin kostenlos, Sie können überprüfen (IIRC). Battlefield 4 hat natürlich auch dieses "Feature". Ein anderes Spiel, in dem Sie dies sehen können, ist "Sniper Elite". 2 oder 3 sind die neueren Titel. Die Physik spielt in diesem Spiel eine wichtige Rolle.
Apache

7

Ich bin auf keinen Fall ein Experte, aber um Ihre Frage zu beantworten, brauchen Sie viele der Dinge, die Sie erwähnen.

Für Ihr 2D-Beispiel könnten Sie eine Position und Geschwindigkeit für eine Kugel haben. (Je nachdem, wie Sie Ihre Aufzählungszeichen implementieren, benötigen Sie möglicherweise auch eine Lebensdauer oder eine maximale Entfernung.) Dies würde normalerweise 2 (x, y) Werte umfassen. Wenn es sich um Floats handelt, sind das 16 Bytes. Wenn Sie 100 Kugeln haben, sind das nur 1600 Byte oder ungefähr 1,5 KB. Das ist heute nichts an einer Maschine.

Als nächstes erwähnen Sie die Sprites. Sie würden nur ein einziges Sprite benötigen, um jede Kugel darzustellen. Ihre Größe hängt von der Bittiefe ab, mit der Sie zeichnen, und davon, wie groß sie auf dem Bildschirm angezeigt werden soll. Sogar unkomprimiert mit 256x256 bei 32 Bit pro Kanal und vollem Float, das ist 1 MB für das Sprite. (Und das wäre sehr groß!) Sie würden dasselbe Sprite an jeder Aufzählungsstelle zeichnen, benötigen jedoch keinen zusätzlichen Speicher für jede Kopie des Sprites. Ähnlich wäre es bei einem On-Hit-Effekt.

Sie erwähnen, dass alle 0,01 Sekunden geschossen wird. Das wären 100 Kugeln pro Sekunde von Ihrer Waffe. Selbst für eine futuristische Waffe ist das ziemlich viel! Laut diesem Wikipedia-Artikel :

Wenn der Abzug gedrückt wird, ist die Rate, mit der die Runden abgefeuert werden, die zyklische Rate. Typische zyklische Feuerraten sind 600–900 U / min für Sturmgewehre, 1000–1100 U / min in einigen Fällen, 900–1200 U / min für Maschinenpistolen und Maschinenpistolen und 600–1200 U / min für Maschinengewehre. M134-Miniguns, die an Kampfhubschraubern und anderen Kampffahrzeugen montiert sind, erreichen eine Feuergeschwindigkeit von über 100 Schuss pro Sekunde (6.000 U / min).

Das wäre also die Rate eines Kampfhubschraubers!

Für eine große Welt, wie Sie sie in Battlefield / Call of Duty / etc. erwähnen, können sie alle diese Geschosspositionen berechnen, aber nicht alle zeichnen, wenn die Aktion weit entfernt ist. Oder sie können sie nicht simulieren, bis Sie sich nähern. (Ich muss zugeben, dass ich in diesem Punkt ein wenig schätze, da ich an nichts so Großem gearbeitet habe.)


6

Wäre es nicht schwierig für den Prozessor, Tausende dieser Objekte zu verarbeiten, die instanziiert und dann zerstört werden (wenn ein On-Hit-Effekt ausgelöst wird)? RAM-Speicher?

Ich denke, Sie unterschätzen, wie schnell Computer sind. Dies war manchmal ein Problem auf den Systemen der 80er und 90er Jahre. Es ist teilweise der Grund, warum die ursprünglichen Space Invaders nicht zulassen, dass Sie eine weitere Kugel abschießen, bis die aktuelle getroffen wurde. Einige Spiele litten unter "Verlangsamung", wenn zu viele Sprites auf dem Bildschirm waren.

Aber heutzutage? Sie verfügen über genügend Prozessorleistung für Tausende von Vorgängen pro Pixel , die zum Strukturieren und Beleuchten erforderlich sind. Es gibt kein Problem mit Tausenden von sich bewegenden Objekten. Auf diese Weise können Sie zerstörbares Gelände (z. B. Red Faction) erstellen, in dem jedes Fragment mit anderen Fragmenten kollidiert und einer ballistischen Kurve folgt.

Algorithmisch muss man ein wenig vorsichtig sein - man kann nicht naiv jedes Objekt mit jedem anderen Objekt vergleichen, wenn man Tausende von Objekten hat. Aufzählungszeichen prüfen im Allgemeinen nicht auf Kollisionen mit anderen Aufzählungszeichen.

Eine kleine Nebenanekdote: Die erste Version von Networked Doom (das Original aus den 90ern) hat für jede abgefeuerte Kugel ein Paket über das Netzwerk gesendet. Wenn ein oder mehrere Spieler das Maschinengewehr bekamen, konnte dies das Netzwerk leicht überfordern. In den 90er Jahren gab es viele Leute, die Doom in Universitäts- oder Arbeitsnetzwerken spielten und Probleme mit ihren Netzwerkadministratoren hatten, als das Netzwerk unbrauchbar wurde.


Ich frage mich, wie die Kettensäge in diesem Zusammenhang
funktioniert hat

1
IIRC, das eigentliche Problem mit dem ersten Netzwerkdoom, besteht darin, dass nicht jedes Paket einzeln an jeden gegnerischen Spieler gesendet werden muss, indem stattdessen Broadcast-Pakete verwendet werden. Dies verringerte die Anzahl der gesendeten Pakete, bedeutete jedoch leider eine erhebliche CPU-Belastung für alle Computer im Netzwerk, einschließlich derer, die das Spiel nicht spielten.
Supercat

1

Ich bin kein Experte, arbeite aber in meiner Freizeit an einem Multiplayer-2D-Shooter-Spiel.

Meine Methode

Zwischen Client und Server gibt es unterschiedliche Aufzählungszeichenklassen (selbst wenn offline gespielt wird, wird eine Serverinstanz in einem separaten Prozess gestartet und über das Hauptspiel verbunden).

Bei jedem Tick (60 pro Sekunde) ermittelt der Client eine Peilung zwischen dem Mauszeiger des Spielers und der Mitte des Bildschirms (wo sich sein Charakter befindet) und es ist Teil der Informationen, die an den Server gesendet werden. Wenn der Spieler in diesem Moment auch feuert (vorausgesetzt, die Waffe ist geladen und bereit), wird eine serverseitige Kugelinstanz mit nur einigen Koordinaten und einem Grundschaden erstellt (der sich aus den Statistiken der Waffe ergibt, die geschossen hat) es). Die Aufzählungsinstanz verwendet dann einige mathematische Funktionen, um eine X- und Y-Geschwindigkeit aus der vom Client erfassten Peilung zu berechnen.

Bei jedem weiteren Tick bewegt sich die Kugel um diese Koordinaten und reduziert ihren Grundschaden um einen vordefinierten Betrag. Wenn dieser Wert unter 1 fällt oder auf ein festes Objekt in der Welt trifft, wird die Aufzählungszeicheninstanz gelöscht, und da das Testen von Punktkollisionen in 2D unglaublich billig ist, haben selbst schnelle Schusswaffen einen vernachlässigbaren Einfluss auf die Leistung.

Was den Client betrifft, werden die Aufzählungszeicheninformationen nicht über das Netzwerk empfangen (es hat sich beim Testen als verschwenderisch erwiesen), sondern als Teil der Aktualisierung pro Tick hat jedes Zeichen einen 'abgefeuerten' Booleschen Wert, der, wenn er wahr ist, einen lokalen Wert erstellt bullet-Objekt, das fast genau wie ein Server-Objekt funktioniert. Der einzige Unterschied besteht darin, dass es ein Sprite hat.

Dies bedeutet, dass die Kugel, die Sie sehen, auf dem Server zwar nicht ganz genau dargestellt wird, ein Unterschied für einen Spieler jedoch kaum spürbar ist und die Netzwerkvorteile etwaige Inkonsistenzen aufwiegen.

Hinweis zu verschiedenen Methoden

Einige Spiele, einschließlich meiner eigenen, bewegen die Kugeln bei jedem Tick wie physische Objekte, während andere nur einen Vektor in Schussrichtung erstellen oder den gesamten Pfad der Kugel in dem Tick berechnen, den sie erstellt hat, z. Strike-Spiele. Es gibt ein paar kleine clientseitige Tricks, um es zu verschleiern, wie eine Animation des Geschossabschusses, aber in jeder Hinsicht ist jedes Geschoss nur ein Laser .

Bei 3D-Modellen mit möglicherweise komplexen Trefferfeldern ist es Standard, Kollisionen ZUERST mit einem einfachen Begrenzungsrahmen zu testen. Gelingt dies, fahren Sie mit einer detaillierteren Kollisionserkennung fort.


0

Es heißt Kollisionserkennung. 8-Bit-Computer verwendeten dazu Player-Missile-Grafiken in Hardware. Moderne Spiele-Engines verwenden Physik-Engines und lineare Algebra. Die aktuelle Richtung einer Waffe wird als 3D-Vektor dargestellt. Das ergibt eine unendliche Linie in Schussrichtung. Jedes sich bewegende Objekt hat eine oder mehrere Begrenzungskugeln, da dies das einfachste Objekt ist, um eine Kollision mit einer Linie zu erkennen. Wenn sich die beiden kreuzen, ist das ein Treffer. Wenn nicht, gibt es keinen Treffer. Aber die Szenerie könnte im Weg sein, so dass auch darauf geachtet werden muss (unter Verwendung von hierarchischen Begrenzungsvolumina). Das nächste Objekt mit einer Kreuzung ist das getroffene Objekt.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.