[Java] Animation hat wischeffekt

NudelMC

Well-known member
ID: 46722
L
16 Juni 2006
178
5
Hoi,

ich bau wiede rin Java :p

Ich hab ne simple Animation gemacht, ein Bild wird einfach von seiner aktuellen position aus nach oben bewegt, allerdings zieht es dabei schlieren :(

Kurz und knapp:
Wie bekomm ich die schlieren weg?
Muss ich da immer den entsprechenden bereich neu einfärben oder gibts da ne andere Lösung?

Danke
Nudel

PS:

Ich hab hier noch das ganze mal geziped:
https://www.progam0r.de/czechman/czechman.zip
Das kann man ausführen und angucken :p
PHP:
import java.awt.*;
import java.awt.event.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Random;
import java.util.Scanner;
import java.util.Date;
import java.io.*;
import java.util.Date;
import java.text.*;


/**
  *
  * Beschreibung
  *
  * @version 1.0 vom 05.02.2007
  * @author
  */

public class Czechman extends Frame {
  // Anfang Variablen
  private Button button1 = new Button();
  Image[] im = new Image[9];
  int x =0;
  private Image dbImage;
  private Graphics dbg;
  // Ende Variablen

  public Czechman(String title) {
    // Frame-Initialisierung
    super(title);
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) { System.exit(0); }
    });
    int frameWidth = 902;
    int frameHeight = 460;
    setSize(frameWidth, frameHeight);
    Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
    int x = (d.width - getSize().width) / 2;
    int y = (d.height - getSize().height) / 2 ;
    setLocation(x, y);
    setLayout(null);

    // Anfang Komponenten
    im[0] = Toolkit.getDefaultToolkit().createImage( "images/bild_01.jpg" );
    button1.setBounds(420, 230, 75, 25);
    button1.setLabel("Los!");
    add(button1);
    // Ende Komponenten
    
      button1.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        button1ActionPerformed(evt);
      }
    });
    setResizable(false);
    setVisible(true);
  }

  // Anfang Ereignisprozeduren
  public void button1ActionPerformed(ActionEvent evt) {
         new Thread(new animation()).start();
  }
  
  // Double Buffering um flackern zu reduzieren
  public void update (Graphics g){
    if (dbImage == null)
    {
      dbImage = createImage (this.getSize().width, this.getSize().height);
      dbg = dbImage.getGraphics ();
    }
    dbg.drawImage(im[0],20,200-x,this);

    paint (dbg);
    g.drawImage(im[0],20,200-x,this);
  }
  
  public void paint(Graphics g) {
    g.drawImage(im[0],20,200-x,this);
  }
  
  // erzeugt die pseudo animation, implements Runnable da es ein extra Thread ist.
  class animation implements Runnable {
  public void run() {
  int i = 0;
         while(i<=50){

           try{
           x=i*3;
           System.out.println("x cords:"+ x);
           Thread.sleep(10);
           repaint();
           }catch(Exception e){
           System.out.println("Fehler");
           }
           i+=1;
         }
         while(i>=0){

           try{
           x=i/3;
           System.out.println("x cords:"+ x);
           Thread.sleep(10);
           repaint();
           }catch(Exception e){
           System.out.println("Fehler");
           }
           i-=1;
         }

  
  }
  }

  // Ende Ereignisprozeduren

  public static void main(String[] args) {
    new Czechman("Czechman");
  }
}
 
du musst in deiner paint-funktion noch
g.clearRect( ...) ausführen, um das alte Bild zu löschen
 
PHP:
  public void paint(Graphics g) {
  g.setColor(new java.awt.Color(0,0,0));
  g.clearRect(800,800,800,800);
  g.drawImage(im[0],playerx,playery,this);
  }

das klappt leider nicht, selbes Problem :(
 
g.clearRect(x,y,width,height)......

aber da liegt dein problem nich ;)
ach NudelMc was bastelst du da scho wieder... ich schaus mir grad ma an

edit:
....
Code:
  public void update (Graphics g){
//Warum nicht in paint?
    if (dbImage == null)
    {
      dbImage = createImage (this.getSize().width, this.getSize().height);
      dbg = dbImage.getGraphics ();
    }
    dbg.drawImage(im[0],20,200-x,this);

    paint (dbg);
    g.drawImage(im[0],20,200-x,this); //Warum?
  }
  
  public void paint(Graphics g) {
    g.drawImage(im[0],20,200-x,this); //Warum hier nochmal?
  }
So jetzt schaust du dir den Code nochma an... Ich frag michvwarum du das Bild 3 mal hinmalst.... ich machs sonst immer anders deswegen kann ich dir hier leider nich die brechstange reichen....

mfg
Samy
 
Zuletzt bearbeitet:
wenn ich dich nicht hätte...

Hier is mal das Aktuellste, soll ein kleines Jump n run für die Schule geben.
läuft auch soweit, man kann die Figur bewegen und springen :)
Jetzt muss er nur noch im springen nach rechts oder links gehen können, dann bin ich für heute zufrieden :)

PS: die import geschichte is übertrieben, das weis ich :)


PHP:
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.*;
import java.awt.event.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Random;
import java.util.Scanner;
import java.util.Date;
import java.io.*;
import java.util.Date;
import java.text.*;


public class KeyLTest extends Frame implements KeyListener{

  // Anfang Variablen
  private Button but = new Button();
  Image[] im = new Image[2];
  int y=0;
  int x=0;
  private Image dbImage;
  private Graphics dbg;
  int springen =0;
  
  
  int playerx=0;
  int playery=520;
  int playerimg=0;
  // Ende Variablen

  KeyLTest()
  {
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) { System.exit(0); }
    });
    int frameWidth = 700;
    int frameHeight = 700;
    setSize(frameWidth, frameHeight);
    Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
    int x = (d.width - getSize().width) / 2;
    int y = (d.height - getSize().height) / 2 ;
    setLocation(x, y);
    setLayout(null);
    but.setBounds(176, 48, 75, 25);
    but.setLabel("button1");
    add(but);
    but.addKeyListener(this);

    setResizable(true);
    setVisible(true);
    
    im[0] = Toolkit.getDefaultToolkit().createImage( "images/playerleft.jpg" );
    im[1] = Toolkit.getDefaultToolkit().createImage( "images/playerright.jpg" );
  }

  public static void main(String[] args) {
    // TODO Auto-generated method stub
    new KeyLTest();
  }

  public void keyTyped(KeyEvent e) {
    // TODO Auto-generated method stub
    System.out.println("TEST1");
  }

  public void keyPressed(KeyEvent e) {
    int k=e.getKeyCode();
    if(k==37){
    // links
    new Thread(new stepLeft()).start();
    }else if(k==38){
    // oben
    if(springen==0){
       new Thread(new springen()).start();
    }
    }else if(k==39){
    //rechts
    new Thread(new stepright()).start();
    }else if(k==40){
    //unten
    System.out.println("unten");
    }
  }
  
  // Double Buffering um flackern zu reduzieren
  public void update (Graphics g){
    if (dbImage == null)
    {
      dbImage = createImage (this.getSize().width, this.getSize().height);
      dbg = dbImage.getGraphics ();
    }
    dbg.setColor(new java.awt.Color(255,255,0));
    dbg.clearRect(200,200,200,200);
    dbg.drawImage(im[playerimg],playerx,playery,this);
    paint (dbg);
    g.drawImage(im[playerimg],playerx,playery,this);
  }

  public void paint(Graphics g) {
  g.setColor(new java.awt.Color(255,255,255));
  g.clearRect(200,200,200,200);
  g.drawImage(im[playerimg],playerx,playery,this);
  }

  //animation, implements Runnable da es ein extra Thread ist.
  class springen implements Runnable {
  public void run() {
  int i = 0;
  springen=1;
         while(i<100){
           try{
           playery-=1;
           Thread.sleep(2);
           repaint();
           }catch(Exception e){
           System.out.println("Fehler");
           }
           i+=1;
         }
         System.out.println("y cords:"+ playery);
         while(i>0){
           try{
           playery+=1;
           Thread.sleep(5);
           repaint();
           }catch(Exception e){
           System.out.println("Fehler");
           }
           i-=1;
         }
         System.out.println("y cords:"+ playery);
  springen=0;
  }
  }
  class stepLeft implements Runnable {
  public void run() {
  int i = 0;
  // Bild links
  playerimg=0;
         while(i<=25){
           try{
           playerx-=1;
           if(playerx<=0){
           playerx=0;
           break;
           }
           Thread.sleep(5);
           repaint();
           }catch(Exception e){
           System.out.println("Fehler");
           }
           i+=1;
         }
         System.out.println("x cords:"+ playerx);
  }
  }
  
  class stepright implements Runnable {
  public void run() {
  int i = 0;
  //Bild rechts
  playerimg=1;
         while(i<=25){
           try{
           playerx+=1;
           if(playerx>=580){
           playerx=580;
           break;
           }
           Thread.sleep(5);
           repaint();
           }catch(Exception e){
           System.out.println("Fehler");
           }
           i+=1;
         }
         System.out.println("x cords:"+ playerx);
  }
  }




  public void keyReleased(KeyEvent e) {
    // TODO Auto-generated method stub
  }
  // Ende Ereignisprozeduren

}
 
Code:
  public void update (Graphics g){
  paint(g);
  }

  public void paint(Graphics g) {
	if (dbImage == null){
	     dbImage = createImage (this.getSize().width, this.getSize().height);
	      dbg = dbImage.getGraphics ();
	}
	dbg.clearRect(0,0, this.getSize().width, this.getSize().height );
        dbg.drawImage(im[playerimg],playerx,playery,this); 
        g.drawImage(dbImage,0,0,this);
  }
Eventuell so?
 
g.clearRect(x,y,width,height)......

... warum du das Bild 3 mal hinmalst.... ich machs sonst immer anders deswegen kann ich dir hier leider nich die brechstange reichen....

mfg
Samy

Das stimmt so würd ich sagen, nennt sich DoubleBuffering und wird hoch und heilig in meinem Buch gelobt :p

Sobald du davon eins rausnimmst läufts nimmer gscheid
 
Code:
  public void update (Graphics g){
  paint(g);
  }

  public void paint(Graphics g) {
	if (dbImage == null){
	     dbImage = createImage (this.getSize().width, this.getSize().height);
	      dbg = dbImage.getGraphics ();
	}
	dbg.clearRect(0,0, this.getSize().width, this.getSize().height );
        dbg.drawImage(im[playerimg],playerx,playery,this); 
        g.drawImage(dbImage,0,0,this);
  }
Eventuell so?

ja oder so :p
Danke:)
 
Bitte :)
Double Buffering setzte ich selber ein und ja du kannst sogar 2 mal das drawImage rausnehmen ;) frag ist halt nur welche.....

Die Update funktion beinhaltet nicht mehr als ein clearAll und dannach das paint.
Man überschreibt sie nur um das clear rauszubekommen welches manchmal paar ns ausmacht bzw flackern dadurch verursacht.
 
Das stimmt so würd ich sagen, nennt sich DoubleBuffering und wird hoch und heilig in meinem Buch gelobt :p
Dann hast Du aber was falsch verstanden oder das Buch hat's falsch beschrieben.

Double Buffering bedeutet, dass Du im Speicher zwei Bereiche zum Grafikzwischenspeichern bereit hälst. Der erste Buffer (Buffer1) im zum Zeichnen da, der zweite (Buffer2) zum Anzeigen. Ist das Bild in Buffer1 fertig gerendert, wird der Speicherbereich in einem Rutsch in Buffer2 kopiert, welchen die Darstellungsroutine immer einfach nur in den Grafikkartenspeicher schaufelt.

Diese Methode hat den immensen Vorteil, dass kein Flackern beim Redraw auftreten dürfte. In Buffer2 liegt immer ein fertiges Bild, das angezeigt werden kann - unabhängig vom Inhalt von Buffer1.