# RPG - Problem : Instanzierte Variablen freigeben



## baroque (28. Mai 2009)

Hi all, 

ich habe vorgestern angefangen Java zu lernen (kann allerdings nicht besonders gut mit Büchern/Tutorials - mehr so learning by doing) und möchte mich nach Pong und 'nem Moorhuhn-Verschnitt jetzt an einem RPG versuchen..dabei kämpft der Spieler durchgehend mit einem Monster, wenn er dieses besiegt hat soll es entfernt werden und anstelle dessen ein neues erscheinen - und das ist das Problem. Sobald ich die Variable = Null setze hängt sich das Applet auf, und ich habe nach diversem rumprobieren leider immer noch keine Ahnung wieso.  Meine Vermutung war, dass Methoden einen Wert der Instanz abfragen obwohl diese gar nicht mehr existiert - ich habe also alle in If-Abfragen verschachtelt bis auf die Abfrage, ob das Monster überhaupt tot ist - die kommt aber im Control Flow vor dem Null-setzen, und hinterher wird auch schon wieder ein neues Monster erschaffen..daran sollte es also nicht liegen. Vielleicht kann mir ja einer von euch helfen? 
Sorry übrigens falls der Code irgendwie unübersichtlich geworden ist, musste bei vielen Dingen zwischendrin ein bisschen basteln/schummeln  falls sich da irgendwas einfacher lösen lässt als ich es gemacht habe bitte auch anmerken, danke!! 

Klasse Charakter : 


```
import java.applet.*;
import java.awt.*;
import java.util.*;
import java.net.*;

public class Charakter
{

	private int level;
	private int HP_Max;
	private int MP_Max;
	private int STAM_Max;
	private int HP;
	private int MP;
	private int STAM;
	private int exp;
	private int exp_tnl;
	private int str;
	private int agi;
	private int intel;
	private int aspd;
	private int aspd_delay;
	private int extraDamage;
	private int lastAttackDamage;
	private int exp_old;



	Random rnd = new Random();




	public Charakter (int lv)
	{

		level = lv;
		exp = 0;
		str = 5;
		agi = 5;
		intel = 5;
		HP_Max = (5 + level) * (1 + str / 5);
		MP_Max = (1 + level / 2) * (1 + intel / 3);
		STAM_Max = (2 + level) * (1 + str / 10 + agi / 20);
		HP = HP_Max;
		MP = MP_Max;
		STAM = STAM_Max;
		extraDamage = 0;
		aspd = 100 + agi;
		
	}

	public void levelUp()
	{
		if(exp >= exp_tnl)
		{	level ++;
			str += rnd.nextInt(3);
			agi += rnd.nextInt(3);
			intel += rnd.nextInt(3);
			HP = HP_Max;
			MP = MP_Max;
			STAM = STAM_Max;
			exp = 0;
		}
	}
	
	public boolean isDead()
	{
		if(HP <= 0)
		{
			HP = 0;
			return true;
		}
		else
		{
			return false;
		}
	}

	public void addExp(int ep)
	{
		exp += ep;
	}

	public void update(int bHP, int bMP, int bSTAM, int bASPD, int bDMG)
	{
		levelUp();
		HP_Max = (5 + level) * (1 + str / 5) + bHP;
		MP_Max = (1 + level / 2) * (1 + intel / 3) + bMP;
		STAM_Max = (2 + level) * (1 + str / 10 + agi / 20) + bSTAM;
		extraDamage = bDMG;
		aspd = 50 + agi / 5 + bASPD;
		exp_tnl = 5 + ((10 * level * level) / (level + level));
		
		if (aspd_delay <= aspd)
		{
			aspd_delay = 200;
		}
		
	}
	
	public int getAttack()
	{
		if(HP > 0)
		{
			aspd_delay --;
			
			if(aspd_delay <= aspd)
			{
				lastAttackDamage = rnd.nextInt(str) + (2 + (str * str / 100)) + extraDamage;
				return lastAttackDamage;

				
			}
			else return 0;
		}
		else return 0;
	}

	public int lastAttack()
	{
		return lastAttackDamage;
	}
	


	public void loseStuff(int h, int m, int s)
	{
		HP -= h;
		MP -= m;
		STAM -= s;
	}
	
	public int getHP()
	{
		return HP;
	}

	public int getMP()
	{
		return MP;
	}

	public int getSTAM()
	{
		return STAM;
	}

	public int getMAX_HP()
	{
		return HP_Max;
	}

	public int getMAX_MP()
	{
		return MP_Max;
	}

	public int getMAX_STAM()
	{
		return STAM_Max;
	}

	public int getEXP()
	{
		return exp;
	}

	public int getEXP_TNL()
	{
		return exp_tnl;
	}

	public int getSTR()
	{
		return str;
	}

	public int getAGI()
	{
		return agi;
	}

	public int getINT()
	{
		return intel;
	}

	public int getASPD()
	{
		return aspd;
	}

	public int getLEVEL()
	{
		return level;
	}

	public int getDELAY()
	{
		return aspd_delay;
	}





		
		
}
```

Klasse Monster :


```
import java.applet.*;
import java.awt.*;
import java.util.*;
import java.net.*;

public class Monster extends Charakter
{
	private int level;
	private int HP_Max;
	private int MP_Max;
	private int STAM_Max;
	private int HP;
	private int MP;
	private int STAM;
	private int exp;
	private int exp_tnl;
	private int str;
	private int agi;
	private int intel;
	private int aspd;
	private int aspd_delay;
	private int extraDamage;
	private int lastAttackDamage;
	public int strbonus;
	private int agibonus;
	private int intelbonus;
	private int extraDamage2;



	Random rnd = new Random();

	int exp_value;
	String mobName;
	

	public Monster (int lv, int type)
	{
		super(lv);
		level = lv;
		exp_value = level / 2 + rnd.nextInt(level) ;
		
		if(type <= 0)
		{
			mobName = "Ogre";
			strbonus = level + rnd.nextInt(level);
			intelbonus = rnd.nextInt(level) + 1;
			agibonus = rnd.nextInt(level) + rnd.nextInt(level) + 1;
			extraDamage2 += level;
		}
		else if (type <= 1)
		{
			mobName = "Spider";
			strbonus = level;
			intelbonus = level;
			agibonus = level + rnd.nextInt(level);
		}

		else if (type <= 2)
		{
			mobName = "Dark Magus";
			strbonus = rnd.nextInt(level);
			intelbonus = 2 * level;
			agibonus = level;
		}
	}




	public String getName()
	{
		return mobName;
	}

	
	public int recieveEXP()
	{
		return exp_value;
	}

	public void mobLevelUp()
	{
		str = strbonus;
		agi = agibonus;
		intel = intelbonus;
		extraDamage = extraDamage2;
	}


}
```

Klasse Main :


```
import java.applet.*;
import java.awt.*;
import java.util.*;
import java.net.*;
import java.awt.event.*;

public class Main extends Applet implements Runnable, MouseListener, KeyListener
{
	Random rnd = new Random();
	Charakter player = new Charakter(1);
	Monster monster1 = new Monster(rnd.nextInt(2) + player.getLEVEL(), 2);

	private Image dbImage;
	private Graphics dbg;
	Thread mainthread;

	public void init()
	{
		addMouseListener(this);
		addKeyListener(this);
		setBackground(Color.black);
	}

	public void start()
	{
		Thread mainthread = new Thread(this);
		mainthread.start();
	}
	
	public void stop()
	{
	}
	
	public void run()
	{
		while(true)
		{

			player.update(0, 0, 0, 0, 0);

			if(monster1 != null)
			{
				monster1.mobLevelUp();
				monster1.update(0, 0, 0, 0, 0);
				monster1.loseStuff(player.getAttack(), 0, 0);
				player.loseStuff(monster1.getAttack(), 0, 0);
				endGame();
			}
			else
			{
				Monster monster1 = new Monster(rnd.nextInt(2) + player.getLEVEL(), rnd.nextInt(2));
			}

			repaint();

			try
			{
				Thread.sleep(20);
			}
			catch(InterruptedException ex)
			{
			}
		}
	}

	public void destroy()
	{
	}

	public void paint (Graphics g)
	{

		g.setColor(Color.red);

		if(player.isDead())
		{
			g.drawString("Game Over! Total Score:", 330, 300);
		}

		if(player.lastAttack() > 0)
		{
			g.drawString("Player attacks! Damage :" + player.lastAttack(), 120, 450);
		}

		if(monster1.lastAttack() > 0)
		{
			g.drawString("Monster attacks! Damage :" + monster1.lastAttack(), 520, 450);
		}

		if(monster1.isDead())
		{
			g.drawString("You defeated " + monster1.getName() + "! Gained " + monster1.recieveEXP() + " Experience Points!", 320, 300);
		}

		////// player-window stats darstellen :

		g.drawString("Player :", 10, 15);
		g.drawString("Level :" + player.getLEVEL(), 10, 35);
		g.drawString("HP :" + player.getHP() + "/" + player.getMAX_HP(), 10, 50);
		g.drawString("MP :" + player.getMP() + "/" + player.getMAX_MP(), 10, 65);
		g.drawString("Stamina :" + player.getSTAM() + "/" + player.getMAX_STAM(), 10, 80);
		g.drawString("Strength :" + player.getSTR(), 10, 95);
		g.drawString("Agility :" + player.getAGI(), 10, 110);
		g.drawString("Intelligence :" + player.getINT(), 10, 125);
		g.drawString("Experience to level :" + player.getEXP() + "/" + player.getEXP_TNL(), 10, 140);
		g.drawString("delay :" + player.getDELAY(), 10, 155);

		////// monster-window stats darstellen :

		g.drawString("Monster :" + monster1.getName(), 700, 15);
		g.drawString("Level :" + monster1.getLEVEL(), 700, 35);
		g.drawString("HP :" + monster1.getHP() + "/" + monster1.getMAX_HP(), 700, 50);
		g.drawString("MP :" + monster1.getMP() + "/" + monster1.getMAX_MP(), 700, 65);
		g.drawString("Stamina :" + monster1.getSTAM() + "/" + monster1.getMAX_STAM(), 700, 80);
		g.drawString("Mob Str :" + monster1.getSTR(), 700, 95);
		g.drawString("Mob Str :" + monster1.strbonus, 700, 110);

	}

	public void update (Graphics g)
	{
		// Initialisierung des DoubleBuffers
		if (dbImage == null)
		{
			dbImage = createImage (this.getSize().width, this.getSize().height);
			dbg = dbImage.getGraphics ();
		}

		// Bildschirm im Hintergrund löschen
		dbg.setColor (getBackground ());
		dbg.fillRect (0, 0, this.getSize().width, this.getSize().height);

		// Auf gelöschten Hintergrund Vordergrund zeichnen
		dbg.setColor (getForeground());
		paint (dbg);

		// Nun fertig gezeichnetes Bild Offscreen auf dem richtigen Bildschirm anzeigen
		g.drawImage (dbImage, 0, 0, this);


	}

	public void mouseClicked(MouseEvent e)
	{
	}

	public void mouseEntered(MouseEvent e)
	{
	}

	public void mouseExited(MouseEvent e)
	{
	}

	public void mousePressed(MouseEvent e)
	{
	}

	public void mouseReleased(MouseEvent e)
	{
	}
	
	public void keyTyped(KeyEvent e)
	{
	}

	public void keyPressed(KeyEvent e)
	{
	}
	
	public void keyReleased(KeyEvent e)
	{
	}

	public void endGame()
	{
		if(player.isDead())
		{
		}
		if(monster1.isDead())
		{
			player.addExp(monster1.recieveEXP());
			monster1 = null;   // ABSTURZ HIER

		}
	}


			
}
```

So, das wars  Vielen Dank schonmal!


----------



## Apo (28. Mai 2009)

Mehrere Sachen:
Da wo es abstürzt ... wieso erstellst du nicht einfach gleich ein neues Monster? und setzt es erstmal auf null?

Außerdem erstellst du in der else Anweisung in der run-Methode ein neues lokales Monster und überschreibst nicht das globale. Nutze für die globalen Sachen einfach this.monster1 usw. Damit bist du dir sicher ob lokal oder global. Und er geht auch nur in den else Zweig wenn das Monster leer ist, dass heisst einen Tick zu spät, weil er davor vlt schon neu zeichnet.
Also erst Überprüfung Monster nicht null -> ok lass es kämpfen -> setzt es auf null -> er geht zu repaint ... -> sleep 20 -> dann erst wieder Überprüfung ob Monster != null

Ich hoffe du konntest mir folgen


----------



## baroque (29. Mai 2009)

Tatsache, dieser eine Tip hat alles zum laufen gebracht. Mein Gott war ich blöd! 
Danke!!! 

*fleissig weiterprog*
Irgendwelche Kommentare zum Code? Ich weiss ich hab da nicht unbedingt konventionsgerecht gearbeitet.. *duck*


----------

