# MouseEvents für Sprites



## System.exit(0) (16. Aug 2015)

Hallo zusammen,

ich versuche gerade, MouseEvents für einzelne Sprites zu implementieren.
Leider ohne Erfolg.
Google und Co haben mir nicht weiter geholfen, da ich irgendwie nicht die passenden Suchbegrife finde 

Das Problem:
Ich habe ein Jpanel, dem ein JFrame hinzugefügt wurde. Dieses besitzt Key- und MouseListener, die auch einwandfrei funktionieren.

In einer weiteren Klasse werden die Sprites (verschiedenen Klassen, alle von meiner Sprite-Klasse abgeleitet) erstellt.

Wie kann ich es jetzt hinbekommen, dass ein MouseEvent ausgelöst wird, wenn die Maus über das Bild des Sprites (wird auf dem JFrame gemalt) gleitet bzw. die Maus auf dem Bild des Sprites gedrückt wird?

Ich möchte, dass das Event direkt in der jeweiligen Instanz der Klasse ausgelöst wird, um zu vermeiden, dass ich die Koordinaten vom JFrame-MouseEvent nehmen muss und dann in allen Sprites nach dem einen suchen muss, der über dieser Koordinate liegt.
Codeversuch in einer Klasse der Sprites:


```
public class Bauwerk extends Sprite implements MouseListener
{
  private Image bild;
  Point koord;
  int schadensgrenze, schaden;
   
  Bauwerk (int x, int y, int schadensgrenze, Image i)
  {
  koord = new Point(x, y);
  this.schadensgrenze = schadensgrenze;
  schaden = 0;
  bild = i;
  }
   
  public void doLogic(long fps)
  {
   
  }
   
  public void drawMe(Graphics g)
  {
  if (bild != null)
  {
  g.drawImage(bild,(int) koord.getX(), (int) koord.getY(), null);
  }else
  {
  System.out.print("\n Kraftwerksbild ist null!");
  }
  }

  @Override
  public void mouseClicked(MouseEvent e)
  {
  System.out.print("\n Maus wurde im Sprite gedrückt");
  }

  @Override
  public void mousePressed(MouseEvent e)
  {
   
  }

  @Override
  public void mouseReleased(MouseEvent e)
  {
   
  }

  @Override
  public void mouseEntered(MouseEvent e)
  {
   
  }

  @Override
  public void mouseExited(MouseEvent e)
  {
   
  }
   
   
}
```

Warum das nicht klappt, ist mir klar. Ich weiß nur nicht, wie ich das implemenieren muss, damit es klappt.

mfg

System.exit(0)


----------



## javampir (16. Aug 2015)

hi,
awt eventlistener können nur components hinzugefügt werden. dein code ist zwar nicht falsch, hat aber unter garantie nicht den effekt den du dir vorstellst, weil es der JVM gar nicht in den sinn kommt, mouseevents für deine sprites auszulösen (slebst wenn du irgendwo eine addMouseListener(irgendeinSprite) hättest).
ich würde das folgendermaßen machen: in deiner klasse sprite eine methode

```
public boolean over(int x, int y)
```
einfügen und diese dann im mouselistener des jpanels bei allen sprites überprüfen (so wie du es wahrscheinlich aus gründen der übersichtlichkeit nicht wolltest). effizienzmäßig bekommst du erst merkliche problemen bei mehreren hundert sprites.


----------



## Major_Sauce (16. Aug 2015)

Nabend, also ausgelöst wird das MouseEvent wenn du die Maus bewegst, ich glaube du wolltest etwas anderes dadurch auslösen.
Im endeffekt ist es ganz einfach, das ist dann schon eine Kollisionserkennung.
Machen wir es mal ganz einfach und sagen deine Sprites und Figuren sind alle rechteckig. Dann musst du einfach nur schauen, und zwar bei jedem MouseEvent :

Das ist jetzt blos pseudocode...
//xMouse = x-Koordinate der Maus
//xSprite = x-Koordinate des Sprites

if(xMouse > xSprite && xMouse < xSprite + spriteWidth) --> Du musst die abfrage auch noch für y machen, wenn dann beide true ergeben dass ist die Maus auf dem Sprite

mfg Major


----------



## System.exit(0) (16. Aug 2015)

Danke,

habe nach weiterem Lesen und den beiden Antworten auch festgestellt, dass das so nicht geht.
Ich habe nun also eine Methode, die einmal pro Zyklus die Mausposition fortschreibt und dann eine einfache Kollisionserkennung.

Ist momentan zu Testzwecken im DrawMe(), kommt aber natürlich woanders hin, so dass der Sprite dann eine boolean isover oder so erhalten kann. Wobei ich mir auch überlege, um das Iterieren über alle Sprites nach isover == true zu sparen, ob ich nicht jedem Sprite eine ID gebe und dann in der Spielsteuerung immer festgehalten wird, welches Sprite gerade isover == true hat.

Dürfte perfomrmanter sein.
In der Spriteklasse

```
public void drawMe(Graphics g, Point mousePos)
  {
       Rectangle r1 = new Rectangle(koord.x, koord.y, bild.getWidth(null), bild.getHeight(null));
       Rectangle r2 = new Rectangle(mousePos.x, mousePos.y, 1,1);
  
       if (!r1.intersects(r2))
       {
            if (bild != null)
            {
                 g.drawImage(bild,(int) koord.getX(), (int) koord.getY(), null);
            }else
       {
       System.out.print("\n Kraftwerksbild ist null!");
  }
```

In der Klasse mit dem JFrame:

```
public Point getMousePos()
       {
       // fragt die Mauspostion ab.
  
       Point temp = new Point(MouseInfo.getPointerInfo().getLocation());
       // Mausposition wird um Position des Spielfeldes korrigiert
  
       temp.setLocation(temp.getX() - this.getLocationOnScreen().x, temp.getY() - this.getLocationOnScreen().y);
       return temp;
       }
```

Wie gesagt, funktioniert ganz gut, muss nur noch so eingebaut werden, dass es
a) übersichtlicher ist,
b) das Iterieren nach dem isover == true Sprite wegfällt
c) das Ganze natürlich aus der drawMe() Methode rauskommt.

mfg

System.exit(0)


----------

