Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

31

09.11.2016, 06:32

Ah ja. Du glaubst also, dass du es bei floats tatsächlich schaffst, dass alle drei Member genau 1,0000000 HP haben, obwohl du vorher immer den Schaden durch 3 (oder N) teilst, somit höchst wahrscheinlich immer sehr nette und für floats nicht darstellbare Kommazahlen bekommst und diese von irgendwas mehrfach abziehst? Man kann sicherlich eine Regel einbauen, die prüft, ob alle genau 1,000000 HP haben, aber was soll das bringen? Sie ist für die Praxis irrelevant. Oder willst du das auch für 2,0000000 und 3,000000 HP einbauen? Oder auch für selektierte Kommazahlen? Wenn dem so ist, dann sind deine floats nutzlos. Der Witz, dass 2 Typen von 3 sterben, tritt ja nur deswegen ein, weil der Schaden eben nicht durch 3, sondern nur durch 2 geteilt wird. Warum du das genau machst, wo du doch gesagt hast, dass durch N teilen kein Problem wäre - und wo alle 3 auch noch leben würden - erschließt sich mir nicht so recht.
Siehst du jetzt den Widerspruch?
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »BlueCobold« (09.11.2016, 06:59)


Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

32

09.11.2016, 10:58

Ah ja. Du glaubst also, dass du es bei floats tatsächlich schaffst, dass alle drei Member genau 1,0000000 HP haben, obwohl du vorher immer den Schaden durch 3 (oder N) teilst, somit höchst wahrscheinlich immer sehr nette und für floats nicht darstellbare Kommazahlen bekommst und diese von irgendwas mehrfach abziehst?

Er hat irgendwann geschrieben dass Rundungsfehler egal sind.
Ich denke allgemein ist das Problem dass hier keiner ein wirkliches Bild von dem hat was du dir vorstellst. Mag sein dass dir selbst völlig klar ist wie sich das ganze verhalten soll, für uns/mich ist das jedoch nicht klar. Nun hast du ja gesagt du hast erst mal ein paar Informationen mit welchen du arbeiten möchtest. Wenn das dann reicht, gut. Ansonsten musst du halt noch mal genau beschreiben was dein erwartetes Ergebnis ist.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

33

09.11.2016, 11:04

Ah ja. Du glaubst also, dass du es bei floats tatsächlich schaffst, dass alle drei Member genau 1,0000000 HP haben, obwohl du vorher immer den Schaden durch 3 (oder N) teilst, somit höchst wahrscheinlich immer sehr nette und für floats nicht darstellbare Kommazahlen bekommst und diese von irgendwas mehrfach abziehst? Man kann sicherlich eine Regel einbauen, die prüft, ob alle genau 1,000000 HP haben, aber was soll das bringen? Sie ist für die Praxis irrelevant. Oder willst du das auch für 2,0000000 und 3,000000 HP einbauen? Oder auch für selektierte Kommazahlen? Wenn dem so ist, dann sind deine floats nutzlos. Der Witz, dass 2 Typen von 3 sterben, tritt ja nur deswegen ein, weil der Schaden eben nicht durch 3, sondern nur durch 2 geteilt wird. Warum du das genau machst, wo du doch gesagt hast, dass durch N teilen kein Problem wäre - und wo alle 3 auch noch leben würden - erschließt sich mir nicht so recht.
Siehst du jetzt den Widerspruch?

Du darfst mir natürlich auch gerne zeigen, wie ich meine Unit nun mit minimalster HP am Leben halte ohne auf einen minimal Wert zu prüfen.

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

34

09.11.2016, 12:13

@anti-freak: kann es sein, dass du meinen Beitrag übersehen hast? Was hältst du von der Alternative, die ich vorgeschlagen habe?
Alternative: Wie viel des eingehenden Schadens verteilt wird, hängt nur vom Lifelink, nicht aber von den angebundenen Einheiten ab. So kann man später dafür sorgen, dass der LifeLink besser oder schlechter wird.
Der LifeLink könnte bspw. pauschal 10 %, 25 %, ... des eingehenden Schadens an die angebundene Einheit weiterleiten. Werden weitere Einheiten angebunden, gilt dafür dann entweder der gleiche Prozentwert oder der Prozentwert könnte von den Anzahl der Links abhängig sein. Weiterhin sollte die Anzahl der Links begrenzt sein.
Erhält der Charakter mehr Schaden, sodass eine angebundene stirbt, könnte der "überschüssige" Schaden verloren gehen oder wieder der Einheit angerechnet werden. Bei letzterem könnte dieser Schaden wieder verteilt werden, oder direkt der Einheit angerechnet werden, als Strafe dafür, dass ein Link zerstört wurde.
Die Verbindungen könnten entweder immer von der Einheit aufgebaut werden, die mit den anderen verbunden werden soll, oder von einer dritten Einheit, die eher als "Supporter" zu bezeichnen wäre. In beiden Fällen könnte es sinnvoll sein, dass nur bestimmte Einheiten diese Fähigkeit anwenden können. Es wäre auch möglich, dass von den ersten beiden Möglichkeiten beides vorhanden ist, es den Supporter aber mehr kosten würde.

Letztendlich ist das eine Game Design Entscheidung, keine Performance-Entscheidung. Man muss auch darauf achten, dass diese Fähigkeit nicht zu stark im Vergleich zu anderen Fähigkeiten wird. Auch muss man darauf achten, dass die Verbindungen dem Spieler am Ende sinnvoll präsentiert werden und dass er diese Verbindungen sinnvoll aufbauen kann.


Ich würde dir, wie aus dem Beitrag vielleicht hervorgeht, stark von einem strikten "am Leben erhalten" abraten. Nicht weil die Implementation dabei problematisch wäre, sondern eher, weil es sonst einen viel zu großen Vorteil liefern würde und ein Balancing mit den anderen Spielmechaniken erschweren würde. Ein Nebeneffekt wäre natürlich, dass man sich um das "Am Leben erhalten" keine Gedanken machen muss, und man könnte tendenziell performantere Implementationen finden, sollte das für dich noch von Bedeutung sein.
Aber wie geschrieben: im wesentlichen ist hier eine Entscheidung bezüglich des Game Design erforderlich.
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

35

09.11.2016, 12:22

Du darfst mir natürlich auch gerne zeigen, wie ich meine Unit nun mit minimalster HP am Leben halte ohne auf einen minimal Wert zu prüfen.
Ich verstehe dein Problem nicht. Du hast Schaden X, den teilst du durch N. Jede Einheit bekommt also S=X/N Schaden. Entweder hat sie mehr HP als das und bleibt am Leben oder sie hat weniger HP als das und ist tot. Wenn dabei ein Overkill auftritt, weil S>HP ist, bleibt ein Rest, den du nun entweder wieder an die restlichen (bedingt durch Rundungsfehler eventuell noch am Leben gebliebenen Member) verteilen musst via S/(N-1), womit der Damage-Algo rekursiv wird, oder du lässt ihn einfach verfallen. Das ist eine Design-Entscheidung.
Wieso aber irgendwas mit minimalstem HP am Leben bleiben sollte, ist mir unklar.
Falls du Angst vor Rundungsfehlern hast oder unbedingt jeden solange wie möglich am Leben halten willst: http://ideone.com/n2SaV3 Hat allerdings die Bedingung, dass HP==0 noch nicht tot ist, sondern erst HP < 0. Ansonsten müsstest du einen Threshold definieren wie tief HP denn mit diesem Algo gehen dürfte. Das ist sicher nicht sinnvoll, weil ja beliebig klein zwischen 0 und 1.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »BlueCobold« (09.11.2016, 12:50)


Thandor

Frischling

Beiträge: 84

Wohnort: Berlin

Beruf: Softwareentwickler

  • Private Nachricht senden

36

09.11.2016, 12:35

Was BlueCobold schreibt erscheint mir auch sehr logisch. So ein Lifelink sollte nicht nur Vorteile bringen sondern auch Risiken.
Ich habe übrigens auch Probleme mir das gewünschte Ergebnis vorzustellen.
Ich mag pewn.de.

37

09.11.2016, 12:36

@anti-freak: kann es sein, dass du meinen Beitrag übersehen hast? Was hältst du von der Alternative, die ich vorgeschlagen habe?
Alternative: Wie viel des eingehenden Schadens verteilt wird, hängt nur vom Lifelink, nicht aber von den angebundenen Einheiten ab. So kann man später dafür sorgen, dass der LifeLink besser oder schlechter wird.
Der LifeLink könnte bspw. pauschal 10 %, 25 %, ... des eingehenden Schadens an die angebundene Einheit weiterleiten. Werden weitere Einheiten angebunden, gilt dafür dann entweder der gleiche Prozentwert oder der Prozentwert könnte von den Anzahl der Links abhängig sein. Weiterhin sollte die Anzahl der Links begrenzt sein.
Erhält der Charakter mehr Schaden, sodass eine angebundene stirbt, könnte der "überschüssige" Schaden verloren gehen oder wieder der Einheit angerechnet werden. Bei letzterem könnte dieser Schaden wieder verteilt werden, oder direkt der Einheit angerechnet werden, als Strafe dafür, dass ein Link zerstört wurde.
Die Verbindungen könnten entweder immer von der Einheit aufgebaut werden, die mit den anderen verbunden werden soll, oder von einer dritten Einheit, die eher als "Supporter" zu bezeichnen wäre. In beiden Fällen könnte es sinnvoll sein, dass nur bestimmte Einheiten diese Fähigkeit anwenden können. Es wäre auch möglich, dass von den ersten beiden Möglichkeiten beides vorhanden ist, es den Supporter aber mehr kosten würde.

Letztendlich ist das eine Game Design Entscheidung, keine Performance-Entscheidung. Man muss auch darauf achten, dass diese Fähigkeit nicht zu stark im Vergleich zu anderen Fähigkeiten wird. Auch muss man darauf achten, dass die Verbindungen dem Spieler am Ende sinnvoll präsentiert werden und dass er diese Verbindungen sinnvoll aufbauen kann.


Ich würde dir, wie aus dem Beitrag vielleicht hervorgeht, stark von einem strikten "am Leben erhalten" abraten. Nicht weil die Implementation dabei problematisch wäre, sondern eher, weil es sonst einen viel zu großen Vorteil liefern würde und ein Balancing mit den anderen Spielmechaniken erschweren würde. Ein Nebeneffekt wäre natürlich, dass man sich um das "Am Leben erhalten" keine Gedanken machen muss, und man könnte tendenziell performantere Implementationen finden, sollte das für dich noch von Bedeutung sein.
Aber wie geschrieben: im wesentlichen ist hier eine Entscheidung bezüglich des Game Design erforderlich.

Nein, ich habe deinen Post nicht übersehen ;) War sogar etwas was ich wirklich gut fand. Ich bin zwar der Server Programmierer, aber nicht alleine für das Game Design verantwortlich. Wir haben das gestern Abend sogar diskutiert, weil mir die Idee wirklich gefällt, allerdings haben wir es erstmal außen vor gelassen, da wir jetzt noch keinen Anwendungsfall dafür haben (und auch voraussichtlich in nächster Zeit nicht haben werden). Allerdings sind wir uns beide einig, dass der LifeLink die Units so lange wie möglich am Leben lassen soll.
Der algo ist jetzt auch kein Hexenwerk.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
Stat LifeLinkComponent::shareDmgWithLifeLinkMembers(Stat _damage, const CastableInfo& _dealerInfo)
{
    Stat totalPoolHp = 0;
    auto pool = _generateUniqueUnitPool(totalPoolHp);
    // kill every member of our pool (except the original unit)
    if (totalPoolHp <= _damage)
    {
        for (auto unit : pool)
        {
            Stat damageToUnit = unit->getHealth();
            unit->applyDamageWithoutModifiers(damageToUnit, _dealerInfo);
            _damage -= damageToUnit;
        }
        return _damage;
    }

    auto poolCopy = pool;
    while (!pool.empty() && _damage > 0)
    {
        auto damageForEach = _damage / (pool.size() + 1);
        auto& unit = *pool.back();
        pool.pop_back();

        static const Stat minHP = 1.f;
        if (unit.getHealth() <= minHP)
            continue;

        auto damageToStayAlive = unit.getHealth() - minHP;
        auto damageToUnit = damageToStayAlive < damageForEach ? damageToStayAlive : damageForEach;
        _damage -= damageToUnit;
        unit.applyDamageWithoutModifiers(damageToUnit, _dealerInfo);
    }

    auto selfHp = m_Unit.getHealth();
    for (auto itr = std::begin(poolCopy); itr != std::end(poolCopy) && _damage >= selfHp; ++itr)
    {
        auto& unit = **itr;
        auto damageToUnit = unit.getHealth();
        _damage -= damageToUnit;
        unit.applyDamageWithoutModifiers(damageToUnit, _dealerInfo);
    }
    return _damage;
}

Im schlechtesten Fall setze ich die HP aller Units auf 1 und muss am Ende noch ein paar Units killen, weil noch zu viel DMG übrig ist.

EDIT: zum Besseren Verständnis muss man sagen, dass das original Unit nicht im pool object drin steckt. Der damage der aus der Methode zurück gegeben wird, der wird dem Unit dann zugefügt. Desweiteren sind die pool Objecte auch anhand ihrer verbliebenen HP sortiert (absteigende Reihenfolge, deswegen fange ich auch von hinten an).

Du darfst mir natürlich auch gerne zeigen, wie ich meine Unit nun mit minimalster HP am Leben halte ohne auf einen minimal Wert zu prüfen.
Ich verstehe dein Problem nicht. Du hast Schaden X, den teilst du durch N. Jede Einheit bekommt also S=X/N Schaden. Entweder hat sie mehr HP als das und bleibt am Leben oder sie hat weniger HP als das und ist tot. Wenn dabei ein Overkill auftritt, weil S>HP ist, bleibt ein Rest, den du nun entweder wieder an die restlichen (bedingt durch Rundungsfehler eventuell noch am Leben gebliebenen Member) verteilen musst via S/(N-1), womit der Damage-Algo rekursiv wird, oder du lässt ihn einfach verfallen. Das ist eine Design-Entscheidung.
Wieso aber irgendwas mit minimalstem HP am Leben bleiben sollte, ist mir unklar.
Dann lies bitte meine anderen Posts. Ich muss das nicht in jedem Beitrag wieder und wieder wiederholen.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

38

09.11.2016, 12:49

Zitat von »BlueCobold«

Falls du Angst vor Rundungsfehlern hast oder unbedingt jeden solange wie möglich am Leben halten willst: http://ideone.com/n2SaV3 Hat allerdings die Bedingung, dass HP==0 noch nicht tot ist, sondern erst HP < 0. Ansonsten müsstest du einen Threshold definieren wie tief HP denn mit diesem Algo gehen dürfte. Das ist sicher nicht sinnvoll, weil ja beliebig klein zwischen 0 und 1.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

CeDoMain

Alter Hase

Beiträge: 587

Wohnort: Ilmenau

Beruf: Student für Mechatronik

  • Private Nachricht senden

39

09.11.2016, 19:26

Ihr dreht euch irgendwie im Kreis... Die Frage war nach einem Algorithmus und ihr verzettelt euch in (Dezimal)-Zahlen. Warum macht ihr nicht jeder einen Vorschlag und dann wird verglichen, wie sich jeder Algorithmus unter verschiedenen Umständen verhält!?

Mein Vorschlag:
Warum muss einkommender Schaden direkt auf die Einheiten aufgeteilt werden? Das ist doch kein Pool mehr, für mich ist das simples verteilen. Pool heißt für mich: Ich hab nen Tank mit 1000 HE und 10 Einheiten, die davon gespeist werden. Schaden wird einfach vom Tank abgezogen. Dann legt man einen Threshhold fest, unter dem eine Einheit tot ist. Bspw. 1. Bei jedem Schaden der zugefügt wird, prüft der Algorithmus einfach, ob der Tank weniger als 10 x 1 HE enthält, denn dann muss zwingend eine Einheit sterben. Falls das nicht der Fall ist, passiert auch nichts weiter. Für mich sieht das erstmal nach super Performance aus. :D

Jetzt stellt man sich die Frage: "Wer stirbt wann". Da gibts für mich diese Kriterien:
- Wer hat den letzten Schaden erhalten
- Wer hat den meisten Schaden erhalten (Absolut oder Ableitungsfunktion)
- Wer kann, wenn er am Leben erhalten wird am meisten ausrichten (bsw. andere töten)
- Wer neigt dazu immer mehr Schaden zu erhalten und kann doch nichts ausrichten (Märtyrertot, damit dem Pool nicht so viel HE angezogen werden)

Es gibt sicherlich noch wesentlich mehr Kriterien, die miteinander verknüpft werden können. Welche man wie einsetzt, hängt auch davon am, auf welche Informationen der Algorithmus noch zugreifen kann, wie intelligent das Ganze sein soll und wie die Kampfstrategie ist. Über sowas sollte man eher diskutieren und noch mehr Vorschläge machen, als über das zu verwendende Zahlenformat und Rundungsfehler. ;)
Mit freundlichem Gruß
CeDo
Discord: #6996 | Skype: cedomain

Lass solche persönlichen Angriffe lieber bleiben, meine sind härter.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

40

09.11.2016, 19:43

Warum macht ihr nicht jeder einen Vorschlag und dann wird verglichen, wie sich jeder Algorithmus unter verschiedenen Umständen verhält!?
Ich habe meinen Vorschlag sogar in C++ umgesetzt und verlinkt. Was willst du mehr?
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Werbeanzeige