Pokemon Attacken unterscheiden

Xym13

Mitglied
Hallo zusammen,

ich bin gerade dabei, eine eigene Pokemon Edition als Android App zu programmieren und bin mir nicht sicher, wie ich die ganzen verschienden Attacke realisieren soll.
Im Moment habe ich nur eine Klasse Attacken. Dort wird halt die Stärke gespeichert und es gibt eine Funktion für den Angriff, in der nach einer Formel der Schaden berechnet wird, die das andere Pokemon erleided.

Das Problem ist jetzt, dass es viele verschiedene Attacken gibt. Welche die nur Schaden austeilen, manche steigen / schwächen Verteidigung, Angriff, manche brauchen 2 Runden usw...

Einzige Lösung die ich hatte, wäre für jede Attacke eine Klasse zu erstellen, die von der "Haupt"-Klasse Attacke erbt und dann in der Angriffsmethode die einzelheiten dort zu beschreiben. Aber mein Bedenken ist dabei, dass ich dann eine riesige Menge an verschiedenen Klassen habe..

Jetzt ist meine Frage, ob es so schlimm, wenn man eine solch riesige Menge an Klassen hat, oder wie man das besser hinbekommt.
 
F

Firephoenix

Gast
Ich bin sicherlich kein Pokemon-Experte, aber das Attackensystem hat doch grob so funktioniert:

-Spieler wählt Attacke aus
-Attacke wirkt Effekt auf den Aktuellen Kampf
-Anderer Spieler ist dran.

Mal ausgehend davon, das du sowas wie ein Kampf-Objekt hast, über das du an beide Kämpfenden Pokemon kommst, dann könntest du dem Kampf doch z.B. so ein Verhalten einbauen:

Für jede Runde:
-Spieler wählt Aktion
-Führe alle aktiven Aktionen (auch alte Aktionen die noch aktiv sind) aus
-Filtere alle fertigen Aktionen

Wenn du dabei der Aktion das Battle übergibst dann wäre ohne Probleme so etwas möglich:

Java:
//in der Battle-Klasse:
Action action = new AnyAction(this);
//später dann zum Ausführen
action.process();

if(action.isFinished()){
//aktion entfernen (z.b. aus liste)
}

Java:
public interface Action{
public void process();
public boolean isFinished();
}

Java:
public class MyAction implements Action{

private Battle battle; //z.b. per Konstruktor übergeben
private boolean finished = false;

//Konstruktor...

public void process(){
Pokemon enemy = //irgendwie den Gegner aus battle besorgen
enemy. //irgendwas mit dem Gegner machen
//evtl ne nachricht in battle ausgeben
finished = true; //fertig
}

public boolean isFinished(){
return finished;
}

}

Alles nur Pseudomäßig angerissen, aber das wäre ein Ansatz den ich selber angehen würde.
Hilft dir das grob weiter?

[EDIT]Für die Attackenvielfalt könntest du z.B. mit Strings als Namen arbeiten, Effekte könntest du auch wiederverwerten (z.B. könnte eine Attacke die 2 Runden lang Schaden machen soll und in der 1. Runde Konfusion + Schaden machen soll intern 2 Felder haben (KonfusionAction + PsychoDamageAction z.B.), dann per counter 2 runden zählen und dannach auch das finished berechnen. Bei Process führst du in runde 1 dann process von konfusion und psychoschaden aus, und in der 2. runde nur noch psychoschaden). Natürlich muss auch die Sammelklasse dann Action implementieren.[/EDIT]

Gruß
 
Zuletzt bearbeitet von einem Moderator:

Xym13

Mitglied
An diese Art von unterscheidung hatte ich auch gedachte. Aber wenn ich nur so unterscheide
Java:
if(attacke.name == "Konfusion") {
....
} else if(attacke.name == "...") {
.....
}

Gibt es dann nicht eine riesige Abfragekette?
Da ist bei mir jetzt die Frage, ist diese lange Kette von Abfragen besser oder für jede Attacke eine Klasse, die dann einfach mit
Java:
attacke.angriff();
ausgeführt wird.
 

Schandro

Top Contributor
Objects mit einheitlichen Methoden (wie z.b. "attack()") sind mit Sicherheit besser als lange "if/elseif" Ketten, solange die Interfaces/Klassen von diesen Objects gut konzipiert sind.

PS:
Java:
attacke.name == "Konfusion"
ist falsch, Strings vergleicht man immer mit .equals:
Java:
attacke.name.equals("Konfusion")
Und am Besten noch getter/setter benutzen:
Java:
attacke.getName().equals("Konfusion")
 
F

Firephoenix

Gast
Strings mit equals() vergleichen =)

Wenn du die Attacken fest jedem Pokemon zuordnest hast du 4? die du Auswählen kannst. Da die Attacken selbst wissen was sie tun reicht es dann auf den aktiven Attacken process() aufzurufen (oder attack() - wie man es halt nennt).

Die Klassenstruktur brauchst du dann nur für unterschiedliches Verhalten (und selbst da kann man noch Klassen wiederverwerten - siehe meinen Edit oben).
Hast du z.B. 4 verschiedene normal-Attacken die nur anderen Schaden haben und einen anderen Namen haben erzeugst du dir halt einmal eine Klasse NormalAttack die das Interface implementiert und zusätzlich halt noch Schaden und Name übergeben bekommt

NormalAttack(Battle battle, String name, int damageToDeal)

da gibt es relativ viele Ansätze ohne so große Lookup-Strukturen denke ich.

Gruß
 

Apo

Bekanntes Mitglied
Ich würde auf Strings verzichten und enums nehmen.

Code:
	public static enum attack {konfusion, bla, blubb};
	
	public void setAttack(attack currentAttack) {
		if (currentAttack == attack.konfusion) {
			System.out.println("ich bin verwirrt");
		} else if (currentAttack == attack.bla) {
			System.out.println("Bla bla bla");
		} else if (currentAttack == attack.blubb) {
			System.out.println("Blubb blubb lubb");
		}
	}

Nur so als Idee.

Ich würde auch für jeden unterschiedlichen Angriff eine Extra-Klasse schreiben und von Standardattacke erben lassen. Vielleicht bietet es sich auch an den Standardangriff noch weiter zu unterteilen: Wenn ich mich recht erinnere, gab es Steinangriffe, Pflanzen etc,
also Vererbungsform: Standardangriff <- Steinangriff <- Steinwurf
 

Niggel595

Mitglied
Moin,

warum baust du dir nicht eine Datenbank auf? Dann sollte das ganz einfach gehen... Du könntest halt einfach Abrfagen à la "Wie viel Schaden macht Attacke XY" machen und die Rückgabe weiterverwenden...

LG
Niggel
 

BRoll

Bekanntes Mitglied
Also bei meinem Pokemon das ich mit C für meinen Taschenrechner programmiert habe,
hab ich die Fälle begrenzt.
Dh. es gibt 100 Attacken mit Original Effekten, dabei aber nur 30 Effekte,
die alle verwenden.
Ich zeig dir mal wie ichs gemacht habe:

Das sind die Attacken-Effekte:
Code:
#define ABSORB 1
#define DEFDOWN 2
#define BURNING 3
#define ICED 4
#define SLEEP 5
#define ATKDOWN 6
#define HITCHANCE 7
#define REPLOW 8
#define REPMIDDLE 9
#define REPHIGH 10
#define SELFDMGLOW 11
#define SELFDMGMIDDLE 12
#define SELFDMGHIGH 13
#define SELFDESTRUCT 14
#define TEMPOUP 15
#define CONFUSED 16
#define GENAUDOWN 17
#define DEFUP 18
#define WAITROUND 19
#define DRACHENWUT 20
#define TIRED 21
#define ONEHIT 22
#define EGELSAMEN 23
#define TOXIN 24
#define WAIT 25
#define CONFUSEDRARE 26
#define REPTWO 27
#define REST 28
#define ULTRASCHALL 29
#define PARALYZED 30
#define INSTANTHIT 31
#define APMINUS 33
#define HEALKP 34
#define LEVELDMG 35
#define TRAUMFRESSER 36
#define ATKUP 37
#define NEXTHITCHANCE 38
#define FAILDMG 39
#define BACKDMG 40
#define REPGEGNATTACK 41
#define INITDOWN 42
#define TOXINRARE 43

Und hier die Attacken-Tabelle:
Code:
//[Schaden,Hitchance,Effekt,AP,Typ]  //0Kratzer           1Heuler											2Glut								3Silberblick							4Schlitzer
unsigned char attackdata[100][5]={{40,100,0,35,NORMAL},{0,100,ATKDOWN,40,NORMAL},{40,100,0,15,FEUER},{0,100,DEFDOWN,30,NORMAL},{70,100,HITCHANCE,20,NORMAL},
// 5Flammenwurf							6Feuerwirbel								7Fluegelschlag				8Bodycheck												9Agilität								10Konfustrahl	
{95,100,BURNING,15,FEUER},{15,70,REPMIDDLE,15,FEUER},{60,100,0,35,FLUG},{90,85,SELFDMGMIDDLE,20,NORMAL},{0,100,TEMPOUP,10,NORMAL},{0,100,CONFUSED,10,NORMAL},
// 11Feuerschlag							12Rauchwolke									13Tackle							14Rutenschlag								15Biss								16Aquaknarre
{75,100,BURNING,15,FEUER},{0,100,GENAUDOWN,20,NORMAL},{35,95,0,35,NORMAL},{0,100,DEFDOWN,30,NORMAL},{60,100,0,25,NORMAL},{40,100,0,25,WASSER},
//17Panzerschutz						18Blubber							19Schädelwumme								20Hydropumpe			21Surfer					22Platscher		    	23Drachenwut
{0,100,DEFUP,40,WASSER},{20,100,0,30,WASSER},{100,100,WAITROUND,15,NORMAL},{120,80,0,5,WASSER},{95,100,0,15,WASSER},{0,100,0,40,NORMAL},{40,100,DRACHENWUT,10,NORMAL},
//24Hyperstrahl							25Klammer							26Guillotine							27Stampfer						28Krabhammer									29Härtner									30Rankenhieb
{150,90,TIRED,5,NORMAL},{55,100,0,30,NORMAL},{0,30,ONEHIT,5,NORMAL},{65,100,0,20,NORMAL},{90,85,HITCHANCE,10,WASSER},{0,100,DEFUP,30,NORMAL},{35,100,0,10,PFLANZE},
//31Egelsamen										32Giftpuder								33Rasierblatt									34Schlafpuder							35Solarstrahl								36Hypnose
{0,90,EGELSAMEN,10,PFLANZE},{0,75,TOXIN,35,PFLANZE},{55,95,HITCHANCE,25,PFLANZE},{0,75,SLEEP,15,PFLANZE},{120,100,WAIT,10,PFLANZE},{0,60,SLEEP,20,PSYCHO},
//37Stakkato										38Wickel											39Hornattacke					40Giftstachel							41Fuchtler								42Doppelkick
{15,85,REPMIDDLE,20,NORMAL},{15,85,REPMIDDLE,20,NORMAL},{65,100,0,25,NORMAL},{15,70,TOXIN,35,NORMAL},{90,100,CONFUSEDRARE,20,NORMAL},{30,100,REPTWO,30,KAMPF},
//43Kopfnuss						44Erholung								45Risikotackle											46Furienschlag							47Hornbohrer							48Donnerschock
{70,100,0,15,NORMAL},{0,100,REST,10,PSYCHO},{120,100,SELFDMGMIDDLE,15,NORMAL},{15,85,REPMIDDLE,20,NORMAL},{0,30,ONEHIT,5,NORMAL},{40,100,0,30,DONNER},
//49Donner							50Superschall								51Ultraschall										52Donnerwelle                53Sternschauer										54Kreideschrei
{120,70,0,10,DONNER},{0,55,CONFUSED,20,NORMAL},{20,90,ULTRASCHALL,20,NORMAL},{0,100,PARALYZED,20,DONNER},{60,100,INSTANTHIT,20,NORMAL},{0,85,DEFDOWN,40,NORMAL},
//55Donnerschlag				56Teleport							57Konfusion								58 Aussetzer				59 Psystrahl				60 Genesung							61 Psychokinese
{75,100,0,10,DONNER},{0,80,TEMPOUP,25,PSYCHO},{50,100,0,25,PSYCHO},{0,80,APMINUS,20,PSYCHO},{65,100,0,20,PSYCHO},{0,100,HEALKP,20,PSYCHO},{90,100,0,10,PSYCHO},
//62 Reflektor					63 Nachtnebel								64Schlecker										65	Hypnose						66 Traumfresser										67 Pfund
{0,100,DEFUP,20,PSYCHO},{0,100,LEVELDMG,15,PSYCHO},{20,100,PARALYZED,30,PSYCHO},{0,60,SLEEP,20,PSYCHO},{100,100,TRAUMFRESSER,15,PSYCHO},{40,100,0,35,NORMAL},
//68 Giftwolke					69 Meditation						70 Karateschlag						71 Fußkick					72 Energiefokus									73 Geowurf
{0,55,TOXIN,40,PSYCHO},{0,100,ATKUP,40,PSYCHO},{50,100,HITCHANCE,25,KAMPF},{65,90,0,20,KAMPF},{0,100,NEXTHITCHANCE,30,NORMAL},{0,100,LEVELDMG,20,KAMPF},
//74 Überroller									75 Fegekick				76 Sprungkick							77 Turmkick							78 Megakick					79 Kometenhieb
{80,80,SELFDMGMIDDLE,25,KAMPF},{60,85,0,15,KAMPF},{70,95,FAILDMG,25,KAMPF},{85,90,FAILDMG,20,KAMPF},{120,75,0,5,NORMAL},{18,80,REPMIDDLE,20,KAMPF},
//80 Eishieb						81 Megahieb					82 Konter									83 Furienschlag							84 Schnabel				85 Spiegeltrick
{75,100,ICED,15,WASSER},{80,85,0,20,NORMAL},{0,100,BACKDMG,20,KAMPF},{15,85,REPMIDDLE,20,NORMAL},{35,100,0,35,FLUG},{0,80,REPGEGNATTACK,20,NORMAL},
//86 Bohrschnabel		87 Windstoß				  	88 Sandwirbel						89 Ruckzuckhieb		90 Slam							91 Barriere							92 Elongation
{80,100,0,20,FLUG},{40,100,0,35,FLUG},{0,100,INITDOWN,15,NORMAL},{40,100,0,30,FLUG},{80,75,0,20,NORMAL},{0,100,DEFUP,30,PSYCHO},{50,80,DEFUP,20,SPECIAL},
//93 Langinator				94 Geniestreich							95 DugehtsRaus					96 Langstrahl				96 Langsieg											97 Säure						98 Stachelspore
{90,80,0,5,SPECIAL},{10,100,REPHIGH,25,SPECIAL},{0,40,ONEHIT,5,SPECIAL},{100,85,0,5,SPECIAL},{200,100,SELFDESTRUCT,1,SPECIAL},{40,100,TOXINRARE,30,PFLANZE},{0,75,PARALYZED,30,PFLANZE},
//99 Erdbeben
{100,100,PARALYZED,INSTANTHIT,NORMAL}
};

Beim Kampf muss eben nur logisch auf diese Effekte geachtet werden,
der Rest der Attacke wird entsprechend des Effektes berechnet.
Somit reduziert man die Fälle schonmal sehr stark.
Und da viele Effekte ähnlich sind kann man dafür auch
zusammenfassende Methoden schreiben, auf die mehrere
Effekte zugreifen können.

Ich denke mal in Java kann man das noch sehr viel vereinfachen,
aber in C muss man halt alles in eine Klasse programmieren-
da wird das noch viel schlimmer :D
 

Ähnliche Java Themen

Neue Themen


Oben