Spave Invanders - Wie zeichne ich die Laser-Schüsse?

Jack159

Bekanntes Mitglied
Hallo,

Ich bin gerade dabei ein Spave Invanders Spiel zu programmieren.

Aktueller Stand:
- Raumschiff (bloßes Viereck)gezeichnet
- Raumschiff steuerbar (Pfeiltasten)
- Raumschiff kann einen Schuss abfeuern mit Leertaste (hier liegt das Problem)


Das Problem besteht darin, dass wenn ich einen Schuss abfeuere und kurz danach noch einen Schuss abfeuern will, der alte Schuss plötzlich verschwindet.

Ich hab schon versucht eine extra Klasse für Schüsse zu erstellen und jedes mal wenn Leertaste gedrückt wird, soll ein seperates Schuss-Objekt erzeugt werden mit eigenen Koordinaten usw.
Das Problem ist aber: Wenn ich Leertaste drücke, befinde ich mich in der keyListener Methode, wo ich mein Schuss-Objekt erstellt habe. Wenn ich nun in der paintComponent Methode auf das Schuss Objekt zugreifen will, exestiert das Objekt ja garnicht mehr, da es ja nur in der keylistener Methode besteht...

Ich hab schon rumprobiert, aber mir fällt keine Lösung mehr ein. Habt ihr vielleicht einen Tipp, wie man das angehen könnte?


Java:
package ABC;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Ellipse2D;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class SpaceInvenderPanel extends JPanel implements KeyListener, ActionListener {
	
	private int x = 300;
	private int y = 400;
	private int dx = 0;
	private int dy = 0;
	
	public int laserX1, laserX2, laserY1, laserY2;
	
    boolean links = false;
    boolean rechts = false;
    boolean oben = false;
    boolean unten = false;
    boolean leertaste = false;
    boolean laserActive = false;
    
    Timer t = new Timer(5, this);
	
    
    //Konstruktor
	public SpaceInvenderPanel(JFrame frame) {
		frame.add(this);
		setFocusable(true);
		addKeyListener(this);
	}
	

	// Zeichnen
	public void paintComponent(Graphics g) {
	    //Raumschiff (Rechteck) zeichnen
		super.paintComponent(g);            
	     Graphics2D g2 = (Graphics2D) g;
	     g2.setColor(Color.BLACK);
	     g2.fillRect(x, y, 30, 30);
	     
	     
	     // Laser-Schuss zeichnen
	     if(leertaste) {
	    
	     g2.drawLine(laserX1, laserY1, laserX2, laserY2);
	     }
	     
	     if(laserActive) {
	    	 laserY1 -= 1;
	    	 laserY2 -= 1; 
	    	 
	    	 g2.drawLine(laserX1, laserY1, laserX2, laserY2);
	    	
	     }

	     
	     t.start();
	   }
	
	
	// Key-Listener
	public void keyPressed(KeyEvent e) {
		

		int code = e.getKeyCode();
		
		if(code==KeyEvent.VK_UP) {
			oben = true;
			
		} else if(code==KeyEvent.VK_DOWN) {
			unten = true;
		
			
		} else if(code==KeyEvent.VK_RIGHT) {
			rechts = true;
		
			
		} else if(code==KeyEvent.VK_LEFT) {
			links = true;
		
		}
		
		
		if(code==32) {
			leertaste = true;
			laserActive = true;
			
			laserX1 = x+15;
			laserX2 = x+15;
			laserY1 = y;
			laserY2 = y-20;
			
		}
		
	}

	
	public void keyReleased(KeyEvent e) {
		

		int code = e.getKeyCode();
		
		if(code==KeyEvent.VK_UP) {
			oben = false;
			
		} else if(code==KeyEvent.VK_DOWN) {
			unten = false;
			
			
		} else if(code==KeyEvent.VK_RIGHT) {
			rechts = false;
			
			
		} else if(code==KeyEvent.VK_LEFT) {
			links = false;
			
		}
		
		
		if(code==32) {
			leertaste = false;
			
		}
		
	}

	
	public void keyTyped(KeyEvent e) {
		
		
	}

	
	public void actionPerformed(ActionEvent e) {
		
		if(oben) {
            dy = -1;
            dx = 0;
            
        }
    
        if(unten) {
        	dy = 1;
        	dx = 0;
        }
        
        if (links) {
        	dy = 0;
        	dx = -1;
        }
        
        if (rechts) {
        	dy = 0;
        	dx = 1;
        }
        
        
        
      
        
   
        
        x +=dx;
        y +=dy;
        repaint();
        dx = 0;
        dy = 0;
		
		
	}



		
	

}

Java:
package ABC;

import javax.swing.JFrame;

public class SpaceInvenderFrame extends JFrame {
	
	public SpaceInvenderFrame(int frameSizeX, int frameSizeY, String frameName) {
		this.setSize(frameSizeX, frameSizeY);
		this.setVisible(true);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setTitle(frameName);
		this.setLocation(500, 200);
	}

}

Java:
package ABC;

public class SpaceInvenderStart {
	
	public static void main(String[] args) {
		
		SpaceInvenderFrame frame = new SpaceInvenderFrame(700, 500, "Space Invander");
		SpaceInvenderPanel panel = new SpaceInvenderPanel(frame);
		
		
		
	}
	

}
 

Fab1

Top Contributor
Hi,

du musst deine Schüsse in einer Liste speichern. Ich habe es mal mit einem Vector gemacht. Anschließend müssen alle Objekte in diesem Vector ständig neu gezeichnet werden.

z.B.

Ich hab eine Klasse Rakete

Java:
import java.awt.Rectangle;


/**
 * Die Klasse Rakete repräsentiert eine Rakete, welche von unserem Raumschiff abgeschossen wird.
 * Sie erbt von Rectangle, denn damit wird die Kollisionerkennung mithilfe von intersect durchgeführt.
 * 
 * @author Fabi
 *
 */
@SuppressWarnings("serial")
public class Rakete extends Rectangle {

	int speed = 3;
	// X Koordinate muss übergeben werden vom Raumschiff
	public Rakete(int x ){
		
		super( x+45 ,480, 10,30);
			
	}
}

Am Anfang erstelle ich einen solchen Vector, welcher die entsprechenden Objekttypen erwartet.

Java:
private Vector<Rakete> raketeListe = new Vector<Rakete>();

ich hatte mir mal eine Methode schießen() geschrieben. Diese kannst wird von KeyPressed() aufgerufen.

Java:
public void schießen(){
		int feuerintervall = 300;		// soviel ms wird gewartet bis zum nächsten Schuss
		
		if (System.currentTimeMillis() - letzterSchuss < feuerintervall) {
			return;
		}

			letzterSchuss = System.currentTimeMillis();	
			
			raketeListe.add(new Rakete(getMouseMoved()));	// X Koordinate von der Maus wird übergeben			
	}

Außerdem habe ich noch eine Methode welche die einzelnen Objekte bewegt. Mittlerweile sollte man Iterator nehmen und nicht mehr Enumeration. siehe auch: Java ist auch eine Insel – 11.2 Mit einem Iterator durch die Daten wandern

Java:
private void moveRakete()
	{
		// Alle Raketen bewegen
		Enumeration<Rakete> e = raketeListe.elements();
		while(e.hasMoreElements())
		{
			Rakete m = e.nextElement();
			m.y = m.y - m.speed;		
		}
	}

und natürlich muss auch geprüft werden ob sich die Objekte schneiden.
Ich muss sagen hier habe ich etwas getrickst, aber kannst dir ja selbst überlegen wie du das anstellen möchtest. Oder welche Vorgabe du hast.

Java:
	public void prüfeKollisionRakete(){
		
		Enumeration<Rakete> r = raketeListe.elements();
		Enumeration<Meteor> m = meteorliste.elements();
		
		
		while(r.hasMoreElements()){
			
			Rakete rak = r.nextElement();
			
			while(m.hasMoreElements()){
				Meteor meteor = m.nextElement();
				
				
				if(rak.intersects(meteor)){
					
					meteorliste.remove(meteor);
					raketeListe.remove(rak);
					punkte +=50;
					punkteAnzeige.setText("Punkte: " + punkte);	
				}
				if(rak.y<10){
					raketeListe.remove(rak);
					
				}
			}
			m = meteorliste.elements();
			
			
		}	
	}

Ich weiß ist jetzt viel Code. Musst das natürlich nicht so machen wie ich. Eventuell ist es eine Hilfe. Vielleicht verwirrt es aber auch mehr.


Speziell bei deinem Problem kann man sagen. Du brauchst eine Liste, diese musst du als Instanzvariable deklarieren, damit alle Methoden der Klasse darauf zugreifen kann. In dieser musst du dann die entsprechenden neu erzeugten Objekte speichern. Und anschließend müssen diese Objekte ständig neu gezeichnet werden und auf Kollisionen mit anderen Objekten geprüft werden.

Hoffe konnte dir helfen.
 

Jack159

Bekanntes Mitglied
Danke für deine Antwort.

Dein Code verwirrt mich leider nur, aber dein Tipp mit der Liste, indem die Objekte gespeichtert werden, klingt intressant. Aber da wüsste ich auch nicht genau, wie ich das umsetzen soll...

Erstelle ich die liste in der SpaceInvandersStart-Klasse und will auf diese dann im keylistener zugreifen, sagt er mir, dass er die liste nicht kennt....???:L
Habs auch als Instanzv. bezeichnet.


Kannst du ein Beispiel geben, was etwas näher an meinem Code ist mit der Liste?
 

Fab1

Top Contributor
Ich muss ganz ehrlich sagen, dass ich das nicht kann. Habe gerade schon angefangen, aber so wirklich will ich nicht verstehen was du da machen willst. Tut mir Leid.
 

Fab1

Top Contributor
Ich verstehe den Code, nicht. Ich schau es mir nochmal an.

Edit:
So ich glaube ich habe jetzt alles drin, damit sich deine Raketen bewegen und alle gezeichnet werden.
Du musst allerdings noch die Methode moveRakete() in die Spielschleife einfügen. Weiß nicht wo du diese hast. Es kann sein das du den ein oder anderen Klassen und Konstruktor Namen wieder anpassen musst, da ich immer in einem Testprojekt arbeite und zu faul bin jedes mal den Klassennamen entsprechend bei mir anzupassen.

Außerdem hab ich wieder mit der Klasse Rakete gearbeitet welche ich oben bereits erwähnt hatte hier nochmal der Code:

Java:
import java.awt.Rectangle;


/**
 * Die Klasse Rakete repräsentiert eine Rakete, welche von unserem Raumschiff abgeschossen wird.
 * Sie erbt von Rectangle, denn damit wird die Kollisionerkennung mithilfe von intersect durchgeführt.
 *
 */
@SuppressWarnings("serial")
public class Rakete extends Rectangle {

	int speed = 3;
	// X Y Koordinate muss übergeben werden vom Raumschiff
	public Rakete(int x, int y ){
		
		super( x ,y, 10,30);
			
	}
}

Und hier der von der Klasse mit dem Panel.

Java:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Test2 extends JPanel implements KeyListener, ActionListener {

	private int x = 300;
	private int y = 400;
	private int dx = 0;
	private int dy = 0;

	private Vector<Rakete> raketeListe = new Vector<Rakete>();

	public int laserX1, laserX2, laserY1, laserY2;

	boolean links = false;
	boolean rechts = false;
	boolean oben = false;
	boolean unten = false;
	boolean leertaste = false;
	boolean laserActive = false;

	Timer t = new Timer(5, this);

	// Konstruktor
	public Test2(JFrame frame) {
		frame.add(this);
		setFocusable(true);
		addKeyListener(this);
	}

	// Zeichnen
	public void paintComponent(Graphics g) {
		// Raumschiff (Rechteck) zeichnen
		super.paintComponent(g);
		Graphics2D g2 = (Graphics2D) g;
		g2.setColor(Color.BLACK);
		g2.fillRect(x, y, 30, 30);

		/*
		 * jedes Objekt in der raketenListe wird ständig neu gezeichnet.
		 */

		Enumeration<Rakete> r = raketeListe.elements();
		while (r.hasMoreElements()) {
			Rakete rak = r.nextElement();
			g.setColor(Color.red);
			g.fillOval(rak.x, rak.y, rak.width, rak.height);
		}

		// Laser-Schuss zeichnen
		/*
		 * if (leertaste) {
		 * 
		 * g2.drawLine(laserX1, laserY1, laserX2, laserY2); }
		 * 
		 * if (laserActive) { laserY1 -= 1; laserY2 -= 1;
		 * 
		 * g2.drawLine(laserX1, laserY1, laserX2, laserY2);
		 * 
		 * // Keine Ahnung, was du da machen willst :-) }
		 */

		t.start();
	}

	private void moveRakete() { // gehört in die Spielschleife, sonst bewegen sich die Raketen nicht.
		/*
		 * Jede erzeugte Rakete wird immer von unten nach oben bewegt.
		 */
		// Alle Raketen bewegen
		Enumeration<Rakete> e = raketeListe.elements();
		while (e.hasMoreElements()) {
			Rakete m = e.nextElement();
			m.y = m.y - m.speed;
		}
	}



	// Key-Listener
	public void keyPressed(KeyEvent e) {

		int code = e.getKeyCode();

		if (code == KeyEvent.VK_UP) {
			oben = true;

		} else if (code == KeyEvent.VK_DOWN) {
			unten = true;

		} else if (code == KeyEvent.VK_RIGHT) {
			rechts = true;

		} else if (code == KeyEvent.VK_LEFT) {
			links = true;

		}

		if (code == 32) {
			leertaste = true;
			laserActive = true;

			laserX1 = x + 15;
			laserX2 = x + 15;
			laserY1 = y;
			laserY2 = y - 20;

		}
		if(code == KeyEvent.VK_SPACE){

				raketeListe.add(new Rakete(x,y));	// X, Y Koords des Raumschiffs		
		}			
			

	}

	public void keyReleased(KeyEvent e) {

		int code = e.getKeyCode();

		if (code == KeyEvent.VK_UP) {
			oben = false;

		} else if (code == KeyEvent.VK_DOWN) {
			unten = false;

		} else if (code == KeyEvent.VK_RIGHT) {
			rechts = false;

		} else if (code == KeyEvent.VK_LEFT) {
			links = false;

		}

		if (code == 32) {
			leertaste = false;

		}

	}

	public void keyTyped(KeyEvent e) {

	}

	public void actionPerformed(ActionEvent e) {

		if (oben) {
			dy = -1;
			dx = 0;

		}

		if (unten) {
			dy = 1;
			dx = 0;
		}

		if (links) {
			dy = 0;
			dx = -1;
		}

		if (rechts) {
			dy = 0;
			dx = 1;
		}

		x += dx;
		y += dy;
		repaint();
		dx = 0;
		dy = 0;

	}

}

Konnte es nicht testen, hoffe aber das es geht.
 
Zuletzt bearbeitet:

Marco13

Top Contributor
Oder so
Java:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class SpaceInvenderPanel extends JPanel implements KeyListener, ActionListener
{

    private int x = 300;
    private int y = 400;
    private int dx = 0;
    private int dy = 0;

    private boolean links = false;
    private boolean rechts = false;
    private boolean oben = false;
    private boolean unten = false;
    private boolean space = false;
    
    private final Timer timer = new Timer(5, this);

    private final double laserSpeed = -4;
    private final double laserLength = 20;
    private final List<Line2D> lasers = new ArrayList<Line2D>();
    private double lastDistance = Float.MAX_VALUE;
    
    // Konstruktor
    public SpaceInvenderPanel(JFrame frame)
    {
        frame.add(this);
        setFocusable(true);
        addKeyListener(this);
        timer.start();
    }

    @Override
    public void paintComponent(Graphics g)
    {
        // Raumschiff (Rechteck) zeichnen
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D)g;
        g2.setColor(Color.BLACK);
        g2.fillRect(x, y, 30, 30);

        g.setColor(Color.RED);
        for (Line2D laser : lasers)
        {
            g2.draw(laser);
        }
    }

    @Override
    public void keyPressed(KeyEvent e)
    {

        int code = e.getKeyCode();

        if (code == KeyEvent.VK_UP)
        {
            oben = true;
        }
        else if (code == KeyEvent.VK_DOWN)
        {
            unten = true;
        }
        else if (code == KeyEvent.VK_RIGHT)
        {
            rechts = true;
        }
        else if (code == KeyEvent.VK_LEFT)
        {
            links = true;
        }
        else if (code == KeyEvent.VK_SPACE)
        {
            space = true;
        }

    }

    @Override
    public void keyReleased(KeyEvent e)
    {
        int code = e.getKeyCode();
        if (code == KeyEvent.VK_UP)
        {
            oben = false;
        }
        else if (code == KeyEvent.VK_DOWN)
        {
            unten = false;
        }
        else if (code == KeyEvent.VK_RIGHT)
        {
            rechts = false;
        }
        else if (code == KeyEvent.VK_LEFT)
        {
            links = false;
        }
        else if (code == KeyEvent.VK_SPACE)
        {
            space = false;
        }
    }

    @Override
    public void keyTyped(KeyEvent e)
    {
    }

    @Override
    public void actionPerformed(ActionEvent e)
    {
        if (oben)
        {
            dy = -1;
            dx = 0;
        }
        if (unten)
        {
            dy = 1;
            dx = 0;
        }
        if (links)
        {
            dy = 0;
            dx = -1;
        }
        if (rechts)
        {
            dy = 0;
            dx = 1;
        }
        x += dx;
        y += dy;
        repaint();
        dx = 0;
        dy = 0;

        if (lastDistance > laserLength * 2)
        {
            if (space)
            {
                lasers.add(new Line2D.Double(x+15, y, x+15, y+laserLength));
                lastDistance = 0;
            }
        }
        else
        {
            lastDistance += Math.abs(laserSpeed);
        }
        
        List<Line2D> toRemove = new ArrayList<Line2D>();
        for (Line2D laser : lasers)
        {
            double x1 = laser.getX1();
            double y1 = laser.getY1();
            double x2 = laser.getX2();
            double y2 = laser.getY2();
            y1 += laserSpeed;
            y2 += laserSpeed;
            laser.setLine(x1, y1, x2, y2);
            
            if (y1 > getHeight())
            {
                toRemove.add(laser);
            }
            if (y2 < 0)
            {
                toRemove.add(laser);
            }
        }
        lasers.removeAll(toRemove);

        System.out.println("Rays: "+lasers.size()+" lastDistance "+lastDistance);
    }

}
 

Jack159

Bekanntes Mitglied
@ Fab1:
Danke für deine Hilfe. Dein Code funktioniert soweit, außer, dass sich die Schüsse bewegen. Aber das muss ja dann in die Spielschleife, welche ich garnicht habe...


@ Marco13:
Danke dir auch.
Dein Code funktioniert soweit. Nur ich verstehe ihn nicht so ganz.

Du erzeugst eine ArrayList vom Typ Line2D, wo Line2D-Objekte reinkommen.

Was bedeutet:
Java:
 private double lastDistance = Float.MAX_VALUE;
?

Dann steht in der paintComponent:

Java:
        for (Line2D laser : lasers)
        {
            g2.draw(laser);
        }
Ich hab grad nochmal nach for-Schleifen gegoogelt, und finde nur welche, die mt einem ";" geschrieben werden. Deine wird aber mit einem ":" geschrieben. Was ist der unterschied bzw. was bewirkt deine for-Schleife genau?


Und unten im ActionListener steht dann:

Java:
if (lastDistance > laserLength * 2) 
        {
            if (space)
            {
                lasers.add(new Line2D.Double(x+15, y, x+15, y+laserLength));
                lastDistance = 0;
            }
        }
        else
        {
            lastDistance += Math.abs(laserSpeed);
        }
        
        List<Line2D> toRemove = new ArrayList<Line2D>();
        for (Line2D laser : lasers)
        {
            double x1 = laser.getX1();
            double y1 = laser.getY1();
            double x2 = laser.getX2();
            double y2 = laser.getY2();
            y1 += laserSpeed;
            y2 += laserSpeed;
            laser.setLine(x1, y1, x2, y2);
            
            if (y1 > getHeight())
            {
                toRemove.add(laser);
            }
            if (y2 < 0)
            {
                toRemove.add(laser);
            }
        }
        lasers.removeAll(toRemove);
 
        System.out.println("Rays: "+lasers.size()+" lastDistance "+lastDistance);
    }

Könntest du einmal kurz und grob in Worte fassen, was genau dein Algorithmus ist, bezüglich der Schüsse?
So wie ich es verstehe:
ArrayList von Typ Line2D machen, wo dann bei Leertastendruck Line2D Objekte erzeugt werden, jedes Objekt mit eigenen Koordinaten.
Sobald ein Laser außerhalb des Fensters ist, wirds gelöscht.
 

Gossi

Bekanntes Mitglied
Ich hab grad nochmal nach for-Schleifen gegoogelt, und finde nur welche, die mt einem ";" geschrieben werden. Deine wird aber mit einem ":" geschrieben. Was ist der unterschied bzw. was bewirkt deine for-Schleife genau?

Java:
for(int i = 0; i < 10; i++) {
     System.out.println(i);
} //ist das gleiche wie
int i = 0;
while(i < 10) {
     System.out.println(i);
     i++;
}

//während
List<String> stringListe = new ArrayList<String>();
for(String str: stringListe) {
     System.out.println(str);
}
//das gleiche ist wie:
List<String> stringListe = new ArrayList<String>();
int i = 0;
while(i < stringListe.size()) {
     String out = stringListe.get(i);
     System.out.println(out);
     i++;
}
 

Jack159

Bekanntes Mitglied
Java:
//während
List<String> stringListe = new ArrayList<String>();
for(String str: stringListe) {
     System.out.println(str);
}
//das gleiche ist wie:
List<String> stringListe = new ArrayList<String>();
int i = 0;
while(i < stringListe.size()) {
     String out = stringListe.get(i);
     System.out.println(out);
     i++;
}


Gilt diese ":" for-Schleife nur bei ArrayLists?
 

Gossi

Bekanntes Mitglied
Gilt diese ":" for-Schleife nur bei ArrayLists?

Nein, bei eigentlich allen Collections, also bei Listen, bei Arrays usw.

Da geht auch sowas (wobei das ja auch im endefeckt nur nen Array is:

Java:
String str = "Java";
for(char c: str.toCharArray()) {
    if(c == 97) {
         System.out.println(""+c);
     }
}

/*Ausgabe:
a
a
*/
 

Marco13

Top Contributor
Gilt diese ":" for-Schleife nur bei ArrayLists?

Kurz: Bei allem, was "Iterable" implementiert, oder bei Arrays.




@ Fab1:
Was bedeutet:
private double lastDistance = Float.MAX_VALUE;
...
Könntest du einmal kurz und grob in Worte fassen, was genau dein Algorithmus ist, bezüglich der Schüsse?
So wie ich es verstehe:
ArrayList von Typ Line2D machen, wo dann bei Leertastendruck Line2D Objekte erzeugt werden, jedes Objekt mit eigenen Koordinaten.
Sobald ein Laser außerhalb des Fensters ist, wirds gelöscht.

Die Beschreibung stimmt soweit. Das mit der lastDistance und die Berechnungen sind dafür da, dass man nur einen Strahl losschicken kann, wenn der letzte schon ein Stück weg ist (sonst würde man das Bild ja mit tausenden Strahlen überfluten...)
 

Jack159

Bekanntes Mitglied
Kurz: Bei allem, was "Iterable" implementiert, oder bei Arrays.






Die Beschreibung stimmt soweit. Das mit der lastDistance und die Berechnungen sind dafür da, dass man nur einen Strahl losschicken kann, wenn der letzte schon ein Stück weg ist (sonst würde man das Bild ja mit tausenden Strahlen überfluten...)

Danke soweit an alle Hilfen ;)

1 Frage habe ich aber noch.

In der actionPerformed-Methode hast du folgendes geschrieben:

Java:
for (Line2D laser : lasers)
        {
            double x1 = laser.getX1();
            double y1 = laser.getY1();
            double x2 = laser.getX2();
            double y2 = laser.getY2();
            y1 += laserSpeed;
            y2 += laserSpeed;
            laser.setLine(x1, y1, x2, y2);
            
            if (y1 > getHeight())
            {
                toRemove.add(laser);
            }
            if (y2 < 0)
            {
                toRemove.add(laser);
            }
        }

Das ganze wird also für jedes laser-Objekt bzw. jeden Schuss durchgeführt, welcher in der lasers-List ist. Wie kommst du aber auf den Objektnamen "laser" ? Du hast den Laser-Objekten doch garkeinen Namen/Referenzvariable bei der erstellung gegeben, wieso funtioniert das dann?

Die Erzeugung der Laser-Objekte sieht ja so aus:

Java:
if (space)
            {
                lasers.add(new Line2D.Double(x+15, y, x+15, y+laserLength));
                lastDistance = 0;
            }

Dort ist aber bei der erstellung eines Laser-Objekts nirgends der Objektname bzw. Referenzvariable "laser" im Spiel.

Oder weist du in der for-each-Schleifenbedienung allen Objekten in der lasers-Liste den Namen "laser" zu, indem zu schreibst
Java:
[code=Java]for (Line2D laser : lasers)
        {.....
?
 

Jack159

Bekanntes Mitglied
Der obige Post von mir kann ignoriert werden, habs nun rausgefunden.

1 Problem habe ich noch:

Der Algorithmus zur beseitigung der Laserschüsse funktioniert nicht. Wollte ihn mal austesten, indem ich sage, dass die Laserschüsse beseitigt werden sollen, sobald sie z.b. y1=200 erreicht haben. Es passiert aber nichts. Der Laserschuss/Laserschüsse fliegen bis zum Ende hin durch, werden also anscheinend nicht beseitigt.

(Variablen teils etwas anders, da ich es nochmal selbst nachprogrammiert hab zum Verständniss)
Java:
List<Line2D> toRemove = new ArrayList<Line2D>();
        for (Line2D laser : laserListe)
        {
            double x1 = laser.getX1();
            double y1 = laser.getY1();
            double x2 = laser.getX2();
            double y2 = laser.getY2();
            y1 -= 10;
            y2 -= 10;
            laser.setLine(x1, y1, x2, y2);
            
            if (y2 < 200)
            {
            	toRemove.add(laser);
            }
           
        }



Habs mal mit
Java:
 if (y2 < 200)
            {
            	laserListe.remove(laser);
            }
probiert. Sobald der erste Laserschuss dann y2=200 erreicht, bekomm ich eine "java.util.ConcurrentModificationException"

???:L
 

Fu3L

Top Contributor
Java:
List<Line2D> toRemove = new ArrayList<Line2D>();
        for (Line2D laser : laserListe)
        {
            double x1 = laser.getX1();
            double y1 = laser.getY1();
            double x2 = laser.getX2();
            double y2 = laser.getY2();
            y1 -= 10;
            y2 -= 10;
            laser.setLine(x1, y1, x2, y2);
            
            if (y2 < 200)
            {
                toRemove.add(laser);
            }
           
        }
laserListe.removeAll(toRemove);

so?
Bei der Bedingung bin ich mir nicht sicher, ob sie Widerspiegelt was du haben willst^^ Nach oben hin werden die y-Werte kleiner. (Angenommen, dass deine Schüsse nach oben fliegen)
 

xehpuk

Top Contributor
Iteriert man mit der foreach-Schleife über eine Liste und sie wird währenddessen verändert (Element hinzugefügt oder entfernt), dann fliegt die genannte Exception.
Daher auch der Umweg über eine temporäre Liste, in der die zu entfernenden Elemente gespeichert werden. Nach der Schleife werden sie dann aus der "richtigen" Liste entfernt.
 

Marco13

Top Contributor
Dass die Bedinung zum Entfernen der Schüsse noch "Probleme" machen könnte, hatte ich mir schon fast gedacht - eigentlich weil ich dachte, dass man auch die x-Koordinate beachten müßte, aber ... bei Space invaders wohl nicht... :oops: genaugenommen braucht man auch die zweite Bedinung nicht, weil die Schüsse ja immer nur nach oben fliegen...
Java:
for (Line2D laser : lasers)
{
...
    if (y1 > 200)
    {
        toRemove.add(laser);
    }
}
lasers.removeAll(toRemove);
sollte gehen...
 

x22

Bekanntes Mitglied
Und warum nennt Oracle selbst das Konstrukt for-each Loop? :reflect:
The For-Each Loop

Gruß

gute Frage.. c# würde es ja einen Sinn geben. Mir wurde damals im Studium eingetrichtert es gibt in java keine for-each. Hab auch tutorials gefunden, in denen "erweiterte for-Schleife" steht.

in den Literaturbüchern von mir zum Thema Java steht auch erweiterte for-Schleife.

foreach würde man ja in c schreiben, java kommt das garnicht vor.
 

Fab1

Top Contributor
Wenn ich "for each" in google eingebe sagt die automatische Vervollständigung erstmal "for each java" das ist ja schonmal :toll::toll:

Ansich geht es ja nur um einen Namen, besser fährt man in Java sicherlich damit wenn man von einer "erweiterten For-Schleife" spricht. Bisher ist mir in meinen gut (erst) 8 Monaten Java diese Benennung noch nie untergekommen.
 

DerFeivel

Bekanntes Mitglied
Gerade gesehen, dass es hier schon geschrieben wurde.


Da es mit 1.5 erst reinkam ist die Gefahr noch allgemein sehr groß, dass viele noch die Le(e)hrmeinung eingetrichtet bekommen haben, dass es in Java kein for-each gibt. :bahnhof:
 
Ähnliche Java Themen

Ähnliche Java Themen

Neue Themen


Oben