# Textbasiertes Kampfsystem



## TheChemist (18. Mai 2009)

Hallo, 
zur Zeit schreibe ich an einem textbasierten Kampfsystem. Immoment ist es so, dass sich die Hauptfigur und der Feind zwar schon bekämpfen können, die "Angriffsgeschwindigkeit" wird allerdings im Prinzip noch durch die Dauer eines Schleifendurchlaufs bestimmt.

Der Klassenaufbau ist folgendermaßen. Monster und Charakter sind Unterklasse von Actor, einer Klasse die alle agierenden Objekte zusammenfasst. Wird ein Actor erzeugt, startet dieser einen Thread in dem sämtliche Berechnungen für diese Figur ablaufen. 

Meine Frage ist: Wie schaffe ich für die Angriffszeit einen festen Wert zu setzen, der unabhängig von der Durchlaufszeit ist?

Code kann ich später posten, sollte er benötigt werden...


----------



## Marco13 (19. Mai 2009)

Code wäre wohl nicht schlecht - oder eine Erklärung des Begriffes "Angriffsgeschwindigkeit"... Sowas wie 
Thread.sleep(1000); // Warte 1 Sekunde
kennst du wohl?


----------



## TheChemist (19. Mai 2009)

Deinen Vorschlag hatte ich  so in Etwa schon probiert, führte allerdings nicht wirklich zum gewünschten Ergebnis.
Hier mal der Code.

Klasse Actor:


```
public class Actor implements Serializable, Runnable {

    protected Gui parent;
    protected String type;
    
    protected int hp;
    protected int dmg;
    protected int level;    
    protected int attackRate;
    
    protected Actor gegner;
    private Thread newActor;
    
    public Actor(Gui parent, String type, int level)
    {
        this.parent = parent;
        this.type = type;
        this.level = level;        
        
        gegner = null;
        
        newActor = new Thread(this);
        newActor.start();
    }
    
    public void run()
    {
        try {
            Thread.sleep(10 + attackRate);
        }catch(Exception e) {

        }
    }
    
    protected void angreifen()
    {
        gegner.getroffen(dmg);
        System.out.println(this.type + " greift " + gegner.getType() + " mit " + dmg + " Schaden an." + gegner.getType() + " hat " + gegner.getHp() + " Leben.");
    }
    
    protected void getroffen(int dmg)
    {
        hp -= dmg;
    }
```

Klasse Monster:


```
public class Monster extends Actor {
    
    private int expReward;
    
    public Monster(Gui gui, String type, int level, Charakter gegner)
    {
        super(gui, type, level);
        this.gegner = gegner;
        
        hp = 50;
        dmg = 3 * level;
        attackRate = 50;       
        
        expReward = level;
    }
    
    public void run()
    {
        while(hp > 0 && gegner.getHp() >= 0) {
            angreifen();
        }
    }

    public int getExp() 
    {
        return expReward;
    } 
}
```

Die Klasse Charakter:

```
public class Charakter extends Actor {

    private String name;
    private Location location;
    
    private boolean kampf;
    private boolean amLeben;
    private int exp;
    private int expNeed;
     
    public Charakter(Gui gui, String type, int level)
    {
        super(gui, type, level);
        
        kampf = false;
        amLeben = true;
        
        hp = 100;
        dmg = level + (level * level);
        attackRate = 100;
        
        exp = 0;
        expNeed = (level + 1) * 2;   
    }
    
    public void run() 
    {
        while(amLeben) {
            if(kampf) {
                if(gegner != null) {
                    Monster gegner = (Monster) this.gegner;
                    angreifen();                    
                    if(gegner.getHp() <= 0) {
                        addExp(gegner.getExp());
                        kampf = false;
                        gegner = null;
                    }
                }
            }
            
            // andere Aktionen
        }
    }
```

Die Ausgabe sieht dann in etwa so aus:

Charakter greift Spinne mit 2 Schaden an.Spinne hat 48 Leben.
Charakter greift Spinne mit 2 Schaden an.Spinne hat 46 Leben.
...
Spinne greift Charakter mit 3 Schaden an.Charakter hat 97 Leben.
...
Charakter greift Spinne mit 2 Schaden an.Spinne hat 4 Leben.
Charakter greift Spinne mit 2 Schaden an.Spinne hat 2 Leben.
Charakter greift Spinne mit 2 Schaden an.Spinne hat 0 Leben.

sollte aber möglichst so in der Art aussehen:
Spinne greift Charakter mit 3 Schaden an.Charakter hat 94 Leben.
Charakter greift Spinne mit 2 Schaden an.Spinne hat 14 Leben.
Spinne greift Charakter mit 3 Schaden an.Charakter hat 91 Leben.
Charakter greift Spinne mit 2 Schaden an.Spinne hat 12 Leben.
Spinne greift Charakter mit 3 Schaden an.Charakter hat 88 Leben.


----------



## Geeeee (19. Mai 2009)

Falls du die Threads behalten willst, dann musst du sie synchronisieren. Schau dir am besten mal Java Insel - Threads synchronisieren dazu an.
Aber mal eine Frage dazu: Warum gibt es nicht "nur" einen Kampfthread, der beide Akteure (oder wieviel auch immer) aufnimmt? Die Idee dabei wäre es dann, dass du einfach über die Beteiligten iterieren könntest, bis nur noch einer steht.
Falls die Kämpfer noch andere Sachen "pseudoparallel" machen sollen, können sie ja auch selber Threads bleiben (mit ordentlicher Synchronisation).


----------



## ARadauer (19. Mai 2009)

ist dir bewusst, dass die run methode von actor nie aufgerufen wird?


----------



## TheChemist (19. Mai 2009)

ARadauer hat gesagt.:


> ist dir bewusst, dass die run methode von actor nie aufgerufen wird?



Ich hab es mir, nachdem ich heute nochmal ausgeschlafen drübergeschaut hab fast gedacht^^
Das sollte ich wohl als erstes ändern. Danach schau ich mir mal die Synchronisations an. Danke für die Antworten.


----------



## Kell0g (21. Mai 2009)

Bin sozusagen bei einem ähnlichem Projekt, also dachte ich, ich schreibe wie ich es getan habe, obwohl ich, als java Anfänger, dir bestimmt nicht weiterhelfe aber vllt nutzt es doch was. 

Habe auch zuerst auf textbasis angefangen, doch da habe ich ich ohne Threads gearbeitet. Hab es dann einfach in der main-Methode  in einer While - schleife ausgeführt, und das ging ganz gut.
Also sowas ähnliches:

while (char.getHP() > 0 || monster.getHP() >0 ) {
   monster.greifeAn(char);
   char.greifeAn(monster);
}
damit es nicht dauernd in der gleichen Reihenfolge abläuft, habe ich da noch eine Zufallszahl eingebaut.
irgendwo istd a shier irgendwo...*mal stübber* ahhhh..
http://www.java-forum.org/spiele-un...-am-einfachsten-auf-gegnerische-werte-zu.html   meine variante...

Nun versuche ich es grafisch umzusetzen und arbeite momentan mit bisher einem Thread.
Da setze ich pro Aktuer einfach eine andere Aktionszeit ein.
Also führt  mein monster solange es lebt z.b  alle 3 Sekunden (Zeit abhängig vom Monster) eine Aktion aus und der Spieler z.b. nach 2,5 Skeunden. 

Da es bei dir automatisch abläuft könntest du doch auch mit boolean Werten arbeiten.
Also Spieler greift an, dann wird wird  Spieler_dran = false gesetzt. wenn Spieler_dran == false, dann ist Monster_dran=true und es kann angreifen.  oder irgendwie so...

Wie gesagt bin ein Anfänger und weiss noch nicht genau was am besten funktioniert also  probiere ich rum.
Hmm...
Vielleicht sollte ich auch pro Aktuer eine eigene Run methode implementieren.


----------



## Geeeee (22. Mai 2009)

Kell0g hat gesagt.:


> while (char.getHP() > 0 || monster.getHP() >0 ) {
> monster.greifeAn(char);
> char.greifeAn(monster);
> }



Ich gehe mal davon aus, dass du anstatt ein || ein && in der while-bedingung hast, sonst wäre das schon Leichenfledderei


----------



## Kell0g (22. Mai 2009)

ähm ja meine ich doch..


----------

