supermario problem (kommen nur zahlen raus)

Status
Nicht offen für weitere Antworten.

rellix

Mitglied
Ich bin noch ein Anfänger in Java und habe ein kleines Problem. ich will ein Super Mario Spiel (natürlich nicht das Echte) programmieren und habe ein Code geschrieben, dann wenn ich aber auf den run-button klicke (bei NetBeans) und das Applet startet kommen nur Zahlen in Millionenhöhe dabei heraus. An was könnte das liegen?

Hier der Code:
Code:
public class supermario extends JApplet implements KeyListener, Runnable {

  private int laenge=80, breite=50, xPos=20,yPos=480-laenge-breite;
  Image status0;
  private Image dbImage;
  private Graphics dbg;
  private boolean moveR = false, moveL = false;
  private int l=0,r=0;
    
    private long delta=System.nanoTime();
    
    @Override
    public void init() {
     setSize(640,480);
     status0=getImage(getCodeBase(),"background.jpg");
     this.addKeyListener(this);
    }
    
    @Override
    public void start() {
     Thread th=new Thread(this);
     th.start();        
    }
    
    public void keyTyped(KeyEvent e) {
    
    }
    
    public void keyPressed(KeyEvent e) {
     if(e.getKeyCode()==KeyEvent.VK_A)
     {
     l=5;
     e.consume();        
     }
     {
     r=5;
     e.consume();
     }
     if(e.getKeyCode()==KeyEvent.VK_D)
     {
     moveR = true;
     r = 5;
     }
     {
     moveL = true;
     l = 5;
     }
    }
    
    public void keyReleased(KeyEvent e) {
    if(e.getKeyCode()==KeyEvent.VK_D)
    {
    moveR = false;
    }    
   }
    
    public void run() {
     Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
     while(true)
     {
      try
       {  
         if(1>0) 
         { 
            xPos-=l*(delta/1e9);
            if (!moveL) l--;
         } 
         else if(r>0)
         {
           xPos+=r*(delta/1e9);
           if (!moveR) r--;
         } 
         Thread.sleep(20);
         repaint();
      }
         catch(InterruptedException ex)
         {
            //nothing
         } 
         Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
      }     
     }   
    
    
    @Override
    public void paint(Graphics g) {
        zeichneHeld(g,xPos,yPos,0);
        g.drawString(""+delta,20,20);
    }
    
    public void zeichneHeld(Graphics g,int x, int y,int status)
    {
        g.drawImage(status0, x, y, this);
    }
    
    @Override
    public void update(Graphics g)
    {
    dbImage = createImage (this.getSize().width, this.getSize().height);
    dbg=dbImage.getGraphics();
    dbg.setColor(getBackground());
    dbg.fillRect(0,0,this.getSize().width,this.getSize().height);
    dbg.setColor(getForeground());
    paint(dbg);
    g.drawImage(dbImage, 0, 0, this);
    } 
    
    
   }
[/code]
 
Weil du effektiv System.nanoTime() (also das delta) ausgibst - und das sind sehr schnell viele Millionen.....
 
Ein paar kleine Änderungsvorschläge, die sich auch etwas auf die Performance auswirken müßten:

Statt:

Code:
    public void update(Graphics g)
    {
    dbImage = createImage (this.getSize().width, this.getSize().height);
    dbg=dbImage.getGraphics();
    dbg.setColor(getBackground());
    dbg.fillRect(0,0,this.getSize().width,this.getSize().height);
    dbg.setColor(getForeground());
    paint(dbg);
    g.drawImage(dbImage, 0, 0, this);
    }

änder mal das so ab:

Code:
    public void update(Graphics g)
    {
    if(dbImage = null){
      dbImage = createImage (this.getSize().width, this.getSize().height);  //<<< create möglichst selten
    }
    dbg=dbImage.getGraphics();
    dbg.setColor(getBackground());
    dbg.fillRect(0,0,getWidth(),getHeight());  //<- getWidht() statt getSize().width
    //dbg.setColor(getForeground());  // <-- das kannst Du weglassen, wenn Du nur Images zeichnest
    paint(dbg);
    g.drawImage(dbImage, 0, 0, this);
    }


Wenn Du Dein Image nicht siehst, können wir das vom Code her schlecht feststellen. Hier solltest Du mal ein paar
System.out.println(...) temporär in Deine Zeichen-Methode einfügen, wo Du z. B. x/y-Position und Breite und Höhe ausgibst. Dann findest Du vielleicht einen Hinweis.
 
Nochwas zu diesem Stück Code:

Code:
         if(1>0)
         {
            xPos-=l*(delta/1e9);
            if (!moveL) l--;
         }
         else if(r>0)
         {
           xPos+=r*(delta/1e9);
           if (!moveR) r--;
         }


Nachdem der else-Zweig auf r>0 abfragt, sollte die If-Bedinung doch vermutlich auf l>0 (statt 1>0) lauten????
 
Hallo erstmal
Tut mir leid, dass ich erst so spät antworten kann.

"Wieso benutzt du den System.nanoTime() ?"

Weil ich in einem Spieletutorial gelesen habe, dass dadurch die Figur flüssiger bewegt werden kann.

@quaxli

Dein Tipp hat mir leider nicht viel genützt, denn jetzt kommt eine Fehlermeldung, nämlich die folgende:

init:
deps-jar:
Compiling 1 source file to D:\Büro\Patrick\NetBeansProjects\SuperMario\build\classes
D:\Büro\Patrick\NetBeansProjects\SuperMario\src\supermario\supermario.java:115: incompatible types
found : java.awt.Image
required: boolean
if(dbImage = null){
1 error
BUILD FAILED (total time: 0 seconds)
 
rellix hat gesagt.:
Code:
if(dbImage = null){

So ist der Ausdruck eine Zuweisung und hat den Typ der Zuweisung, also ein Image.

Gefragt ist hier aber ein Boole'scher Vergleich, also
Code:
if(dbImage == null){
 
rellix hat gesagt.:
"Wieso benutzt du den System.nanoTime() ?"

Weil ich in einem Spieletutorial gelesen habe, dass dadurch die Figur flüssiger bewegt werden kann.

Das würde aber mindestens voraussetzen, dass delta in der Schleife jeweils neu gesetzt wird; etwa so
Code:
while (...) {
  delta = System.nanoTime() - delta;
}

Dann enthält delta die Anzahl von Nanosekunden seit dem letzten Schleifendurchlauf. Daraus kann man über einen konstanten Faktor einen Offset bestimmen, der zur letzten Position hinzuaddiert werden muss, um eine Bewegung mit konstanter Geschwindigkeit zu erreichen, auch wenn die Schleife mal schneller und mal langsamer läuft.

Für den Anfang würde ich das aber weglassen und mit einem konstanten Offset arbeiten.
 
Quaxli hat gesagt.:
Nochwas zu diesem Stück Code:

Code:
         if(1>0)
         {
            xPos-=l*(delta/1e9);
            if (!moveL) l--;
         }
         else if(r>0)
         {
           xPos+=r*(delta/1e9);
           if (!moveR) r--;
         }

kann man auch verkürzen zu:

Code:
            xPos-=l*(delta/1e9);
            if (!moveL) l--;

Da 1 immer größer als 0 ist

(zumindest im Jahr 2008 noch 😎 )

Falls der Trollversuch gescheitert sein sollte, bitte ignorieren.
 
Leroy42 hat gesagt.:
Da 1 immer größer als 0 ist

(zumindest im Jahr 2008 noch 😎 )

Das sollte immer noch so sein 😉
Ich vermute aber, daß die "1" ein "l" sein soll. 😉

@rellix:
Bin auch dafür, daß Du mal den aktuelle Code postest -wie von murray gewünscht.
 
Hier der gewünschte Code:
Code:
package supermario;

import java.awt.*;
import java.net.*;
import java.awt.event.*;
import javax.swing.*;

/**
 *
 * @author Administrator
 */
public class supermario extends JApplet implements KeyListener, Runnable {

  private int laenge=80, breite=50, xPos=20,yPos=480-laenge-breite;
  Image status0;
  private Image dbImage;
  private Graphics dbg;
  private boolean moveR = false, moveL = false;
  private int l=0,r=0;
    
    private long delta=System.nanoTime();
    
    @Override
    public void init() {
     setSize(640,480);
     status0=getImage(getCodeBase(),"background.jpg");
     this.addKeyListener(this);
    }
    
    @Override
    public void start() {
     Thread th=new Thread(this);
     th.start();        
    }
    
    public void keyTyped(KeyEvent e) {
    
    }
    
    public void keyPressed(KeyEvent e) {
     if(e.getKeyCode()==KeyEvent.VK_A)
     {
     l=5;
     e.consume();        
     }
     {
     r=5;
     e.consume();
     }
     if(e.getKeyCode()==KeyEvent.VK_D)
     {
     moveR = true;
     r = 5;
     }
     {
     moveL = true;
     l = 5;
     }
    }
    
    public void keyReleased(KeyEvent e) {
    if(e.getKeyCode()==KeyEvent.VK_D)
    {
    moveR = false;
    }    
   }
    
    public void run() {
     Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
     while(true)
      try
       {  
         if(l>0) 
         { 
            xPos-=l*(delta/1e9);
            if (!moveL) l--;
         } 
         else if(r>0)
         {
           xPos+=r*(delta/1e9);
           if (!moveR) r--;
         } 
         Thread.sleep(20);
         repaint();
      }
         catch(InterruptedException ex)
         {
            //nothing
         }
     while(true) {
        delta = System.nanoTime() - delta; 
     }
         Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
      }     
        
    
    
    @Override
    public void paint(Graphics g) {
        zeichneHeld(g,xPos,yPos,0);
        g.drawString(""+delta,20,20);
    }
    
    public void zeichneHeld(Graphics g,int x, int y,int status)
    {
        g.drawImage(status0, x, y, this);
    }
    
    @Override
    public void update(Graphics g) 
    { 
    if(dbImage == null){ 
      dbImage = createImage (this.getSize().width, this.getSize().height); 
    } 
    dbg=dbImage.getGraphics(); 
    dbg.setColor(getBackground()); 
    dbg.fillRect(0,0,getWidth(),getHeight()); 
    //dbg.setColor(getForeground()); 
    paint(dbg); 
    g.drawImage(dbImage, 0, 0, this); 
    }
    
   }
 
Was bezweckst Du mit diesem
Code:
     while(true) {
        delta = System.nanoTime() - delta;
     }
Code in der run-Methode?
Damit hängt der Thread in einer Endlosschleife fest.
 
Hallo erstmal,

@Murray

ich habe deinen Rat befolgt und den von dir beschriebenen Code rausgelöscht, hat LEIDER NICHTS genützt

Ich bitte weiterhin noch um Hilfe

DANKE schonmal
 
Was soll denn dieser Code
Code:
    public void keyPressed(KeyEvent e) {
     if(e.getKeyCode()==KeyEvent.VK_A)
     {
     l=5;
     e.consume();       
     }
     {
     r=5;
     e.consume();
     }
     if(e.getKeyCode()==KeyEvent.VK_D)
     {
     moveR = true;
     r = 5;
     }
     {
     moveL = true;
     l = 5;
     }
    }
bewirken?
 
Ich hab' mal dran rumgefrickelt, damit es halbwegs läuft. Ist aber stellenweise kein sehr schöner Code, aber Du kriegst hoffentlich in etwa ein Idee, wie man es aufbauen könnte:

Code:
package src;

import java.applet.Applet;
import java.awt.*;
import java.net.*;
import java.awt.event.*;
import java.awt.geom.Rectangle2D;

import javax.swing.*;


// Den Code, den Du ausgesucht hast ist für Applet, nicht JAppelt
// Wenn Du Swing nutezn willt, pack ein JPanel in ein JApplet, dann mußt Du die Doppelbufferung nicht proggen

public class SM extends Applet implements KeyListener, Runnable {

	Image status0;
	private Image dbImage;
	private Graphics dbg;
	private boolean moveR = false, moveL = false;
	private long delta = 0;
	private long last = 0;
	int speed = 100;
	
	Rectangle mario;  //Bildersatz

	@Override
	public void init() {
		setSize(640, 480);
		setBackground(Color.BLACK);
		// jpg habe ich jetzt nicht
		// status0=getImage(getCodeBase(),"background.jpg");
		addKeyListener(this);
		last = System.nanoTime();
		
		mario = new Rectangle(50,50,30,30); //Das ist jetzt mal mein Mario - eigentlich müßte das eine eigene Klasse sein.
	}

	@Override
	public void start() {
		Thread th = new Thread(this);
		th.start();
	}

	public void keyTyped(KeyEvent e) {

	}

	public void keyPressed(KeyEvent e) {
		
		// Steuerung über Boolean, damit auf mehr als eine Taste reagiert werden kann
		if (e.getKeyCode() == KeyEvent.VK_LEFT) {
			moveL = true;
		}

		if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
			moveR = true;
		}
	}

	public void keyReleased(KeyEvent e) {

		if (e.getKeyCode() == KeyEvent.VK_LEFT) {
			moveL = false;
		}

		if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
			moveR = false;
		}

	}

	public void run() {

		while (true){

			//delta auskaspern und last neu setzen
			delta = System.nanoTime() - last;
			last = System.nanoTime();
			
			//Mario bewegen
			moveMario();
			
			//Päuschen
			try{
				Thread.sleep(10);
			} catch (InterruptedException ex) {}
			
			//pinseln
			repaint();
		}
	}
	
	private void moveMario(){
		
		// Der Zugriff auf die Variablen von "Mario" ist so extrem unschön. Üblicherweise läuft das in einer eigenen Methode
		// innerhalb einer eigenen Klasse. Hier nur auf die Schnelle mal so.
		int deltax = (int)(speed*delta/1e9);
		
		if(moveL){
			mario.x-= deltax;
		}
		
		if(moveR){
			mario.x+= deltax;
		}
		
		//Grenzen des Applets checken
		if(mario.x<=0){
			mario.x = 0;
			moveL = false;
		}
		
		if(mario.x+mario.width>=getWidth()){
			mario.x = getWidth()-mario.width;
			moveR = false;
		}
		
	}
	
	

	@Override
	public void paint(Graphics g) {
		g.setColor(Color.RED);
		g.drawRect(mario.x, mario.y, mario.width, mario.height);
		g.drawString("" + delta, 20, 20);
	}


	@Override
	public void update(Graphics g) {
		super.update(g);
		if (dbImage == null) {
			dbImage = createImage(this.getSize().width, this.getSize().height);
		}
		dbg = dbImage.getGraphics();
		dbg.setColor(getBackground());
		dbg.fillRect(0, 0, getWidth(), getHeight());
		// dbg.setColor(getForeground());
		paint(dbg);
		g.drawImage(dbImage, 0, 0, this);
	}

}
 
Status
Nicht offen für weitere Antworten.

Zurück
Oben