Ich brauche eine Idee: Animation mit teil eines Bildes

sambacket

Mitglied
Guten Abend,

Folgendes: Ich habe eine Animation erstellt, die halt sehr stark flackert. Das Problem bei dieser Animation ist, dass ich die Bilder nicht im Vorfeld laden kann und so das System mit dem Dubblebuffer nicht einsetzen kann.

Animation:

Ich habe ein 2Dspiel, wo eine Umgebungs-Karte als Jpeg vorliegt. Meine Figur befindet sich in der Mitte des Bildschirms. Nun wird, im Hintegrund, immer nur der Teil der Karte(vom Jpeg) geladen, wo die Figur sich grad aufhält...

Das habe ich ganz einfach mit g2d.draw gelöst....Es gibt die Option Teilbereiche eines Bildes zu zeichnen...Wie kann ich es nun umsetzen, dass die Animation, sprich das Neuladen der Karte nicht flackert.

1.update überschreiben funzt nicht, da er die updatefunktion nicht aufruft.
2. animation hab ich mit threads gelöst

Bitte eine Idee..

Danke

Sam
 
Versuche es mit VolatileImages und setze die Regionen, in den gezeichnet wird mit setClip möglichst klein, sodass nur kleine Teile des Bildes neu gezeichnet werden müssen. Das Problem dabei wird möglicherweise sein, dass die VolatileImages keinen Alpha-Kanal haben. In diesem Fall würde ich zumindest die Karte als VolatileImage halten und das, was Du darüber zeichnest als BufferedImage darüber zeichnen.
 
Zuletzt bearbeitet:
Also ich bräuchte noch ein paar Informationen:
1) Mit welchen Klassen arbeitest du? Wo wird gezeichnet. JPanel oder Canvas?
2) Was wird denn genau animiert? Die Figur? Oder meinst du mit Animation nur die Map, die sich verschiebt. (Oder hat die Animationen wie Wasser etc. ? )
3) Wieso muss das Bild im vorfeld geladen sein, damit du es mit einem DoubleBuffer verwenden kannst??

Also die einfachste Lösung (und auch die gängigste) ist ein Doppel Puffer, mit dem du Zeichnest. Am einfachsten in einem Canvas mit einer BufferStrategy. Du kannst natürlich auch in einem JPanel zeichnen. Da kannst du den Doppel Puffer aktivieren ( oder ist er glaube ich standartmäßig )
 
Zur näheren Beschreibung habe ich noch ein BIld entworfen..Siehe Anhang


Es ist grad ganz schön wichtig, da ich Montag ne Abgabe hab

Danke
 

Anhänge

  • ansicht.jpeg
    ansicht.jpeg
    24,3 KB · Aufrufe: 39
Bei jeden Neuzeichnen:

Java:
public void paint(Graphics g) {
   g2d.drawImage(img, 0, 40, 400, 440, p.getX()-212, p.getY()-192, p.getX()+189, p.getY()+208, null);
}

Ich zeichne quasi das Bild neu.Eeinen Ausschnitt aus dem Bild:

Geladen habe ich es in der init() methode des applets:

Java:
ImageIcon i = new ImageIcon(Pfad);
img = i.getImage();
 
mh. die idee ist eigentlich richtig. das flackern kommt daher, das dein bild im applet erst gelöscht wird und dann neu gezeichnet wird. und da dein pc nicht unendlich performance hat, flackert es dann, weil ein gelöschter Bildschirm einfach weiß ist. Die frage ist, wie rufst du in deinem Thread auf, dass gezeichnet werden soll? Bestimmt mit repaint(); Weil wenn du repaint aufrufst, wird automatisch auch update() aufgerufen. Die Methode müsste dann folgendermaßen aussehen:
Java:
/** Update - Methode, Realisierung der Doppelpufferung zur Reduzierung des Bildschirmflackerns */
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);

}

Und warum lädst du die Bilder nicht mit
Java:
Applet.getImage (Applet.getCodeBase (), "image.jpg");

Oder zeichnest du mit einer anderen Graphickomponente??
 
Das mit dem Update probier ich:

Als Grafikobjekt nehm ich ein ImageIcon

Java:
ImageIcon i = new ImageIcon(this.getCodeBase().getPath()+"zusegame/Bilder/museum_neu.jpg");
img = i.getImage();

Wenn ich es mit mit deinen Vorschlag probiere

Java:
Image img;
img = Applet.getImage (Applet.getCodeBase (), "image.jpg");

sagt er mir...


non-static method getCodeBase() cannot be referenced from a static context
Image img = Applet.getImage (Applet.getCodeBase (), "image.jpg");
 
In dem Applet kannst du das "Applet" durch "this" ersetzen.

Abgesehen davon: Wenn du ein JApplet verwendest, erübrigt sich das ganze: Bei Swing ist DoubleBuffering schon eingebaut....
 
Ja ich benutze ein JApplet.

hab jetzt auch die Update methode eingebaut, aber leider spricht er die Methode nicht an.

Aber wenns schon eingebaut ist...was dann..wie bekomm ich das flackern weg..

Das war ja mein Problem..
 
Fertig..obwohl er bei dem Beispiel..irgendwie die Grafik nur anzeigt, wenn ich die Größe des Applet verändere. In meinem Programm funzt es auf diese Weise..halt nur mit Flackern.

Aber man trotzdem erkennen, wie die Animation läuft

Java:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JApplet;


public class NewJApplet extends JApplet implements Runnable {

  
    Image umgebung,spieler;
    Point spielerpos = new Point(540,440);
    
    public void init() {

        // TODO start asynchronous download of heavy
        ImageIcon i = new ImageIcon("Umgebung.jpg");
        umgebung = i.getImage();
        ImageIcon j = new ImageIcon("Figur.png");
        spieler = j.getImage();
       

          Thread th = new Thread(this);
         th.start();
    }

    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2d = (Graphics2D) g;
         g2d.drawImage(spieler,200,200,null);
         g2d.drawImage(umgebung, 0, 0, 400, 400, spielerpos.x-200, spielerpos.y-200, spielerpos.x+200, spielerpos.y+200, null);
         spielerpos.x= spielerpos.x+10;

    }
     
    public void run(){

          //neu pinseln
            repaint();
            try {
                Thread.sleep(100); //Päuschen
            } catch (InterruptedException ex) {}
        
        }
    public void start(){

          run();
        }


  
}
 
Besser?
Java:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.JApplet;


public class NewJApplet extends JApplet implements Runnable {


    Image umgebung,spieler;
    Point spielerpos = new Point(540,440);


    class ImagePanel extends JPanel
    {
        public void paintComponent(Graphics g)
        {
            Graphics2D g2d = (Graphics2D) g;
             g2d.drawImage(spieler,200,200,null);
             g2d.drawImage(umgebung, 0, 0, 400, 400, spielerpos.x-200, spielerpos.y-200, spielerpos.x+200, spielerpos.y+200, null);
             spielerpos.x= spielerpos.x+10;
        }
    }

    public void init() {

        // TODO start asynchronous download of heavy
        ImageIcon i = new ImageIcon("circleImage01.jpg");
        umgebung = i.getImage();
        ImageIcon j = new ImageIcon("circleImage02.jpg");
        spieler = j.getImage();

        setLayout(new GridLayout(1,1));
        add(new ImagePanel());

          Thread th = new Thread(this);
         th.start();
    }


    public void run()
    {
        while (true)
        {
          //neu pinseln
            repaint();
            try {
                Thread.sleep(100); //Päuschen
            } catch (InterruptedException ex) {}

        }
    }



}
 

Zurück
Oben