# UNMÖGLICHe "Nullpointer"-Exception



## Androbin (17. Jun 2014)

Hali-Hallo liebe Community,
ich habe hier ein [STRIKE]kleines[/STRIKE] großes Problem *8*

Ich habe "MineCraft" nachprogrammiert (in 2D) und bin gerade damit fertig geworden,
das Spiel auf "Open World" umzukrempeln, dachte ich jedenfalls *8*

1. kommt es an bestimmten Stellen vor, dass das Spiel "einfriert", also ÜBERHAUPT nicht mehr reagiert,
2. WICHTIG(er)*:* Gibt es auch "Nullpointer"-Exceptions, welche ich mir ÜBERHAUPT nicht erklären kann !!!

Da mein (bisheriger) Code zu lange ist, um ihn komplett zu posten und mir nicht klar ist, welche Klasse(n) relevant ist/sind *8*
Stelle ich den kompletten Source-Code in den Anhang !!!

Auch wenn mir bewusst ist, dass sich das keiner extra downloaden will, hier meine Bitte *8*
Helft mir den/die Fehler zu finden (und wenn möglich, zu beheben) !!!


----------



## Gucky (18. Jun 2014)

Relevant ist der Code, der die Exception hervorruft. Poste doch den mal.


----------



## Joose (18. Jun 2014)

Also ich habe mir mal deinen SourceCode angeschaut und mir haben sich die Zehennägel aufgestellt :shock:


```
public  HashMap  <Point  , Block > world   = new HashMap  <Point  , Block >();
    private HashMap  <Integer, Double> heights = new HashMap  <Integer, Double>();
    public  ArrayList<      Mob      > mobs    = new ArrayList<      Mob      >();
    
    private ArrayList<BufferedImage  > blocks                                             ;
    private           BufferedImage[]  characterPics = new           BufferedImage[ 3 ]   ;
    private           BufferedImage    logo                                               ;
    private ArrayList<BufferedImage[]> mobPics       = new ArrayList<BufferedImage[   ]>();

		setBackground( Color.GRAY );
		
		setFocusable    ( true );
		addKeyListener  ( this );
		addMouseListener( this );
		
		BufferedImage image = null;
		
		try   { image = ImageIO.read( ResourceLoader.class.getResource("/net/diegamingbrueder/games/MineKlex/res/Steve.png" ) ); }
		catch ( Exception e ) { e.printStackTrace(); }
		
		int width    = image.getWidth () / 3;
		int height   = image.getHeight()    ;
		
		characterPics[ 0 ] = image.getSubimage( 0        , 0, width, height );
		characterPics[ 1 ] = image.getSubimage(     width, 0, width, height );
		characterPics[ 2 ] = image.getSubimage( 2 * width, 0, width, height );
```

Diese ganzen Leerzeichen sind einfach nur schlecht für den Lesefluss. Klar du findest dich vielleicht zurecht usw.
Aber viele werden sich den Code so gar nicht anschauen wollen, weil es einfach zu unübersichtlich ist! 

Und teilweise hast du viele Leerzeilen mittem im Code .... die machen alles wieder länger


```
for ( int p = -1; p <= 1; p++ )
	            try   { mob [ p  + 1 ] = ImageIO.read( ResourceLoader.class.getResource("/net/diegamingbrueder/games/MineKlex/res/mobs/" + mobType.name + "_" + p + ".png" ) ); }
				catch ( Exception e ) { e.printStackTrace(); }

    	for ( int y = 0; y < ItemsLengthY; y++ )
    	for ( int x = 0; x < ItemsLengthX; x++ )
    		if ( Items[ x ][ y ] == null ) {
    			
    			 Items[ x ][ y ] = new ItemStack( type, number );
    			return;
    			
    		}
```

Du probierst überall Zeilen zu sparen indem du bei einzeiligen if-Bedingungen oder for-Schleifen die Klammer weglässt. Zwar ist das valide, aber die meisten tun sich einfacher beim Lesen mit Klammern! Da sofort erkennbar ist wo denn die Schleife/Bedigung anfängt und aufhört.


Ansonsten zu deiner NullPointer Exception: Du hast uns zwar den SourceCode gegeben, aber sonst nichts was zum Ausführen des Projektes wichtig wäre (Resourcen -> Bilder). Somit ist ein ausführen und nachstellen der Exception nicht möglich. Weiters reicht es einfach uns die Exception inkl StackTrace und dem entsprechenden Code zu posten!


----------



## Androbin (18. Jun 2014)

Joose hat gesagt.:
			
		

> Diese ganzen Leerzeichen sind einfach nur schlecht für den Lesefluss. Klar du findest dich vielleicht zurecht usw.
> Aber viele werden sich den Code so gar nicht anschauen wollen, weil es einfach zu unübersichtlich ist!


Also ich finde es viel übersichtlicher und es tut mir leid, wenn ihr das anders seht !!!



			
				Joose hat gesagt.:
			
		

> Du hast uns zwar den SourceCode gegeben, aber sonst nichts was zum Ausführen des Projektes wichtig wäre (Resourcen -> Bilder).


'tschuldige, ich tue den Ressource-Ordner in den Anhang !!!


----------



## Joose (18. Jun 2014)

Androbin hat gesagt.:


> Also ich finde es viel übersichtlicher und es tut mir leid, wenn ihr das anders seht !!!



Wie gesagt, es ist natürlich möglich das du dich zurecht findest. Das würde ich natürlich auch wenn ich mich etwas damit beschäftige würde usw.
Willst du aber später beruflich als Programmierer arbeiten wirst du es mit so einem Code schwer haben bei den anderen Kollegen, viele Firmen haben entsprechende Code Konventionen (wie hat Code auszuschauen etc). Noch dazu wirst du es dann vl schwerer haben anderen Code zu lesen wenn er nicht deiner Formatierung entspricht.

Außerdem ist es mühsam solchen Code zu warten. Beispiel:

```
private           BufferedImage[]  characterPics = new           BufferedImage[ 3 ]   ;
private ArrayList<BufferedImage[]> mobPics       = new ArrayList<BufferedImage[   ]>();
```

Wenn du nun die Größe von "characterPics" auf 100 änderst musst du ja bei jedem Array mehr Leerzeichen einfügen damit die Klammern untereinander stehen. Oder was ist wenn du statt der ArrayList eine LinkedList verwenden willst/musst, dann müssen in der 1.Zeile wieder Leerzeichen hinzufügt werden nur damit das "BufferedImage[]" untereinandersteht.

Aber es gibt kein Gesetz, welches vorschreibt wie Code auszusehen hat. Aber es hilft anderen und dir wenn man sich an bestimmte übliche Konventionen hält.



Androbin hat gesagt.:


> 'tschuldige, ich tue den Ressource-Ordner in den Anhang !!!



Schön ... jetzt wäre noch der StackTrace der Exception hilfreich. Der verrät dir ja schon wo genau die Exception auftritt. Möglicherweise lässt sich der Fehler beheben ohne das man das ganze dafür debuggen muss.


----------



## Androbin (18. Jun 2014)

Joose hat gesagt.:
			
		

> Schön ... jetzt wäre noch der StackTrace der Exception hilfreich. Der verrät dir ja schon wo genau die Exception auftritt. Möglicherweise lässt sich der Fehler beheben ohne das man das ganze dafür debuggen muss.


OK, hier der StackTrace *8*

```
Exception in thread "Thread-39" java.lang.NullPointerException
	at net.diegamingbrueder.games.MineKlex.Character.move(Character.java:188)
	at net.diegamingbrueder.games.MineKlex.Character.run(Character.java:230)
	at java.lang.Thread.run(Unknown Source)
```


----------



## Joose (18. Jun 2014)

Da braucht man ja nur auf den Code schauen um den möglichen Fehler zu finden:


```
int rx  = (int) RX ;
int ry1 = (int) RY1;
int ry2 = (int) RY2;
int ry3 = (int) RY3;
				
Block r1 = world.world.get( new Point( rx, ry1 ) );
Block r2 = world.world.get( new Point( rx, ry2 ) );
Block r3 = world.world.get( new Point( rx, ry3 ) );
				
if ( r1.getId() != 0
   || r2.getId() != 0
   || r3.getId() != 0 ) {
```

Zuerst einmal der Cast von 
	
	
	
	





```
double
```
 nach 
	
	
	
	





```
int
```
 kann schon mal ungewollte Effekte habe? Hast du diesen Part kontolliert?


```
world.world.get
```
 gibt dir einfach null zurück wenn es für den gewünschten Punkt keinen Block gibt. Da du hier gar keine Prüfung hast fliegt dir natürlich bei dem Zugriff in der if-Bedingung die NullPointerException. 

Also diese NPE ist nicht so unmöglich wie du behauptest!


----------



## Androbin (18. Jun 2014)

Joose hat gesagt.:
			
		

> Da du hier gar keine Prüfung hast fliegt dir natürlich bei dem Zugriff in der if-Bedingung die NullPointerException. Also diese NPE ist nicht so unmöglich wie du behauptest!


1. Das muss ich auch nicht, denn
2. ist sie das doch, denn sobald der Spieler sich bewegt, wird die Welt "gescrollt"
und sollten an den zu zeichnenden Stellen keine Blöcke sein, werden diese automatisch vorher gerendert.
Sollte sich also an jener Stelle kein Block befinden dürfte er auch gar nicht angezeigt werden !!!


----------



## Tobse (18. Jun 2014)

Androbin hat gesagt.:


> und sollten an den zu zeichnenden Stellen keine Blöcke sein, werden diese automatisch vorher gerendert.
> Sollte sich also an jener Stelle kein Block befinden dürfte er auch gar nicht angezeigt werden !!!



Offensichtlich doch. Mal den debugger drangestzt?


----------



## Joose (18. Jun 2014)

Androbin hat gesagt.:


> 1. Das muss ich auch nicht, denn



Wenn du etwas aus einer Liste holen willst das es nicht gibt dann hast du nichts mit dem man arbeiten kann -> NullPointerException

Willst du daher mit diesem Objekt weiterarbeiten dann musst du vorher sicherstellen das es diese Objekt gibt! 



Androbin hat gesagt.:


> 2. ist sie das doch,



Sie ist nicht unmöglich, du bekommst sie ja. 



Androbin hat gesagt.:


> denn sobald der Spieler sich bewegt, wird die Welt "gescrollt"
> und sollten an den zu zeichnenden Stellen keine Blöcke sein, werden diese automatisch vorher gerendert.
> Sollte sich also an jener Stelle kein Block befinden dürfte er auch gar nicht angezeigt werden !!!



Ja schön und gut, so stellst du es dir vor! 
Das Problem ist aber, dass du einen Fall hast wo das ganz und gar nicht funktioniert! 
Ich würde generell einfach eine Prüfung einbauen an besagter Stelle ob es diese Blöcke überhaupt gibt. Solche Überprüfungen gehören einfach zu entsprechender Fehlerbehandlung die jedes Programm auch Spiele brauchen. 

Meiner Meinung nach liegt das Problem in der Synchronisation der beiden Threads (World und Character) das du die Fehlermeldung bekommst! Da beide unabhängig voneinander laufen wird sich der Character bewegen und auf Blöcke zugreifen die im Thread World noch nicht hinzugefügt wurden!

=> Baue Logausgaben und Fehlerbehandlungen ein, arbeite anfänglich vl nur mit einer zentralen GameLoop welche die Eingaben behandelt und alle Objekte steuert.


----------



## Joose (18. Jun 2014)

Jetzt will ich das Ding mal ausführen -> öffnet sich ein JFileChooser

Was soll ich ihn denn öffnen lassen ich habe doch noch gar nichts! :bahnhof::bahnhof::bahnhof:

[EDIT]Ah, ok wenn ich nichts angebe passt es anscheinend. So eine Information wäre auch noch hilfreich [/EDIT]


----------



## Androbin (18. Jun 2014)

Joose hat gesagt.:
			
		

> Jetzt will ich das Ding mal ausführen -> öffnet sich ein JFileChooser
> 
> Was soll ich ihn denn öffnen lassen ich habe doch noch gar nichts!


Das habe ich vergessen, zu sagen *8*
Wer eine Welt hat, kann sie hier laden, (nicht notwendig)
sonst abbrechen, dann wird automatisch eine generiert


----------



## Joose (18. Jun 2014)

Ok habe mich ein bisschen herumgespielt, so wie es ausschaut bewegt sich der Character irgendwann schneller als sich die World neu aufbauen kann! Somit probiert der Character auf Blöcke zuzugreifen, welche es nicht gibt.

Lösung => Synchronisation der beiden Threads! Der Spieler darf sich erst weiterbewegen nach X/Y wenn sie die Welt hier schon aufgebaut hat.
Mehr kann ich dir dazu nicht sagen, da ich nicht gewillt bin mich in diesen Code einzulesen (keine gute Formatierung, keine Fehlerbehandlung und auch keine Log-/Konsolenausgaben)


----------



## Androbin (18. Jun 2014)

> Ok habe mich ein bisschen herumgespielt, so wie es ausschaut bewegt sich der Character irgendwann schneller als sich die World neu aufbauen kann! Somit probiert der Character auf Blöcke zuzugreifen, welche es nicht gibt.


So müsste es funktionieren *8*

```
Point up1 = new Point( ux1, uy );
Point up2 = new Point( ux2, uy );

if ( !world.world.containsKey( up1 ) )
      world.expand( ux1, uy );

if ( !world.world.containsKey( up2 ) )
      world.expand( ux2, uy );

Block u1 = world.world.get( up1 );
Block u2 = world.world.get( up2 );
```
Allerdings friert das Spiel immer noch ein ...


----------



## Tobse (18. Jun 2014)

Androbin hat gesagt.:


> So müsste es funktionieren *8*
> 
> ```
> Point up1 = new Point( ux1, uy );
> ...



Die Geschwindigkeit mit der sich der Spieler bewegt steigt exponentiell. Die Geschwindigkeit, mit der der PC blöcke nachlegen kann ist irgendwann an einer Grenze. Da einfach ein Limit reinbauen + den Code von Androbin und es sollte eigentlich funktionieren.


----------



## Androbin (18. Jun 2014)

So verrückt es auch klingt, aber anscheinend liegt der Fehler irgendwo im Welt-Scrolling, denn
wenn man in der Klasse Character das Scrollen für die X-Koordinate wegkommentiert,
dann hängt es sich nicht auf und [STRIKE]alles[/STRIKE] fast alles ist [STRIKE]wieder[/STRIKE] in Butter !!!
Die Frage lautet also *8* "Wo liegt das Problem im Scrollen (welches das Spiel einfrieren lässt) ???"


----------



## Androbin (18. Jun 2014)

Tobse hat gesagt.:
			
		

> Die Geschwindigkeit mit der sich der Spieler bewegt steigt exponentiell. Die Geschwindigkeit, mit der der PC blöcke nachlegen kann ist irgendwann an einer Grenze. Da einfach ein Limit reinbauen + den Code von Androbin und es sollte eigentlich funktionieren.


Da muss ich dir [STRIKE]leider[/STRIKE] widersprechen *8*

```
if ( speedX < maxSpeed )
     speedX++;
```


----------



## Androbin (18. Jun 2014)

Androbin hat gesagt.:
			
		

> So verrückt es auch klingt, aber anscheinend liegt der Fehler irgendwo im Welt-Scrolling, denn
> wenn man in der Klasse Character das Scrollen für die X-Koordinate wegkommentiert,
> dann hängt es sich nicht auf und [STRIKE]alles[/STRIKE] fast alles ist [STRIKE]wieder[/STRIKE] in Butter !!!
> Die Frage lautet also *8* "Wo liegt das Problem im Scrollen (welches das Spiel einfrieren lässt) ???"


PS: Das Problem tritt nur auf, wenn sich der Spieler nach rechts bewegt
und zwar jenseits des "Scrolling-Ereignis-Horizontes", wie er zu Beginn existiert !!!


----------



## Ruzmanz (18. Jun 2014)

Oje, wenn du als Schöpfer des Quellcodes nichtmal den NPE aufspühren kannst ... Du solltest ALLES in EINEN Thread packen. Wenn du mehrere Thread hast, musst du dich um die Synchronisation kümmern. Das setzt viel Erfahrung vorraus.


----------



## Androbin (18. Jun 2014)

Ruzmanz hat gesagt.:
			
		

> Du solltest ALLES in EINEN Thread packen.


OK, schon geschehen !!!
Im Anhang der momentane Code.


----------



## Androbin (19. Jun 2014)

Allerdings friert es immer noch ein !!!


----------



## Ruzmanz (19. Jun 2014)

Laut deinem letzten Upload implementiert die Klasse Inventory Runnable.

PS: Anstatt einen haufen Quellcode zu zippen könntest du gleich auf öffentliche Versionsverwaltungstools setzen: http://www.java-forum.org/deployment/161078-svn-server-mieten-erfahrungen.html#post1023710 / http://www.java-forum.org/softwaree...assenaustausch-kollegen-projekt-arbeiten.html


----------



## MR_UNIX (19. Jun 2014)

Ich bin gerade am Handy und kann daher seinen Code nicht (optimal) durch gucken, trotzdem aber zwei kurze Kommentare meinerseits:
1. Eine NullPointerException die auftritt kann nicht unmöglich sein, sie ist ja aufgetreten. Manchmal sind die einfach sehr gut versteckt, man sagt ja immer "der Teufel sitzt im Detail"
2. Bitte gewöhne dir die Ausrufezeichen ab. Nach normalen Sätzen macht man Punkte. Wenn man ein Ausrufezeichen nutzt, dann dazu, um etwas nachdrücklich zu machen. Und selbst dann nur ein Ausrufezeichen. "Satzzeichen sind keine Rudeltiere" 

Wenn das Problem morgen noch nicht gelöst ist, schaue ich natürlich auch mal mit, vielleicht kann ich ja helfen. So wie vor mir bereits geschrieben wurde, hängt es oft mit unterschiedlichen Threads zusammen.


----------



## Joose (20. Jun 2014)

Androbin hat gesagt.:


> Allerdings friert es immer noch ein !!!



Wie gesagt baue zusätzlich noch Logausgaben ein und verwende den Debugger.
Damit findest du raus das es anscheinend zu einer Endlosschleife in 
	
	
	
	





```
World.paintComponent(Graphics g)
```
 kommt. Warum und weshalb weiß ich nicht, habe auch nicht die Lust den (für mich) unlesbaren Code zu verstehen usw.


----------



## Androbin (21. Jun 2014)

: MR_UNIX *8*
Das Problem mit der NPE ist jetzt gelöst, das Problem besteht jetzt darin *8*


			
				Androbin hat gesagt.:
			
		

> So verrückt es auch klingt, aber anscheinend liegt der Fehler irgendwo im Welt-Scrolling, denn
> wenn man in der Klasse Character das Scrollen für die X-Koordinate wegkommentiert,
> dann hängt es sich nicht auf und alles fast alles ist wieder in Butter !!!
> Die Frage lautet also 8 "Wo liegt das Problem im Scrollen (welches das Spiel einfrieren lässt) ???"





			
				Androbin hat gesagt.:
			
		

> PS: Das Problem tritt nur auf, wenn sich der Spieler nach rechts bewegt
> und zwar jenseits des "Scrolling-Ereignis-Horizontes", wie er zu Beginn existiert !!!


[EDIT]
Es friert bereits davor ein.
Aber wieso nur nach rechts und nur rechts vom Spawn-Point?
[/EDIT]
[OT]
Satzzeichen jetzt besser?
[/OT]
: Joose *8*
Wie/Wo soll es DORT zu einer Endlos-Schleife kommen? Erklärung bitte!


----------



## Androbin (23. Jun 2014)

Bug behoben *8*
Vorher *8*

```
public void expand( int x, int y ) {
...

int s = 0;

     if ( x * Block.size + Block.size + sX < getWidth() ) s =  1;
else if ( x * Block.size              + sX > getWidth() ) s = -1;

...
```
Nachher *8*

```
...

int s = 0;

     if ( x < 0 ) s =  1;
else if ( x > 0 ) s = -1;

...
```


----------

