2D-Grafik Animation flackert

  • Themenstarter Themenstarter Daniel1993
  • Beginndatum Beginndatum
D

Daniel1993

Gast
Sehr geehrte Mitglieder dieses Forums,
ich habe in meiner Schule das Unterrichtsfach programmieren und uns wurde heute
das programmieren von Animationen näher gebracht.

Meine Aufgabe ist es eine flüssige Animation zu programmieren, da meine stark flackert.

Ich habe 3Klassen, welche ich präsentiere und es wäre nett, wenn mir jemand sagt wie ich den Quellcode umschreiben muss, um eine
flüssige Animation zu erhalten.

Klasse 1: Fenster
Java:
import java.awt.event.*;
import java.awt.*;

public class Fenster extends Frame
{
    Man man = new Man ("Planet.png",0,0);
    
    public Fenster()
    {
        this.add(man);
        this.setTitle("Weltraumanimation");
        this.setSize(1280,819);
        this.show();
        this.addWindowListener(new FensterMitXSchliessen());
        
        for (int x = 50; x <= 1000; x++)
        {
            man.setBounds(x,100);
            delay(10);
            man.repaint();
        }
    }
    
    public void delay(int ms)
    {
        try
        {
            Thread.currentThread().sleep(10);
        }
        catch (InterruptedException e)
        {}
    }
    
    public static void main (String[] args)
    {
        Fenster f = new Fenster();
    }
}

Klasse 2: Man
Java:
 import java.awt.*;

public class Man extends Canvas
{
    private Image image;
    int xPos, yPos;
    
    public Man(String imagePath, int x, int y)
    {
        image = loadImage (imagePath);
        xPos = x;
        yPos = y;
        setBackground(Color.blue);
    }
    
    public void paint (Graphics g)
    {
        Image Weltall = Toolkit.getDefaultToolkit().getImage("Weltall.jpg");
        g.drawImage(Weltall,0,0,this);
        g.drawImage(image, xPos, yPos, null);
    }
    
    public void setBounds(int x, int y)
    {
        xPos = x;
        yPos = y;
    }
    
    public Image loadImage (String imagePath)
    {
        Image image = Toolkit.getDefaultToolkit().getImage(imagePath);
        return image;
    }
}

Klasse 3: Fenster mit X Schließen
Java:
 import java.awt.event.*;
public class FensterMitXSchliessen extends WindowAdapter
{
    public void windowClosing(WindowEvent e)
    {
        System.exit(0);
    }
}

Als Editor nutze ich BlueJ

Ich würde mich gerne über Hilfe freuen

mfg Daniel
 
und uns wurde heute
das programmieren von Animationen näher gebracht.
Hat man da auch das Thema Threads und EDT erwähnt? Sollte man diesbzgl. kennen.

Ansonsten sollte in der
Code:
paint(Graphics g)
möglichst nur gezeichnet und schon gar keine Bilder geladen werden. Zumal es grundsätzlich unsinnig ist ein Bild immer wieder neu zu laden.
 
Also das Weltall Bild wird als Hintergrund geladen und uns wurde nicht gesagt wo man es sonst einbinden kann.
Leider wurden uns Threads sowie EDT nicht gelehrt.
Jedoch bin ich für weiterbildung offen.

Wie sollte ich denn das Bild Planet.png einbinden, um es nicht immer wieder neu zu laden?

Uns wurde das so beigebracht: Bild laden, löschen, laden ,löschen bis zum endpunkt
(Wie ein Daumenkino)
 
Stichworte AWT und DoubleBuffering, verwende statt AWT (Frame, Canvas) lieber Swing (JFrame, JComponent - dort dann paintComponent überschreiben), Swing ist automatisch double buffered...
 
Wird dadurch das flackern behoben?

Wenn ja könntest du mir kurz erklären was ich bei swing anderst schreiben muss als bei awt oder ob sich nur die Bibliothek sowie
die Klasseneröffnung ändert?
 
Habe swing benutzt und nun folgen Fehlermeldung: cannot find symbol - class Image

Quellcode:

Java:
import javax.swing.*;

public class Man extends JComponent
{
    private Image image;
    int xPos, yPos;
    
    public Man(String imagePath, int x, int y)
    {
        image = loadImage (imagePath);
        xPos = x;
        yPos = y;
        setBackground(Color.blue);
    }
    
    public void paint (Graphics g)
    {
        Image Weltall = Toolkit.getDefaultToolkit().getImage("Weltall.jpg");
        g.drawImage(Weltall,0,0,this);
        g.drawImage(image, xPos, yPos, null);
    }
    
    public void setBounds(int x, int y)
    {
        xPos = x;
        yPos = y;
    }
    
    public Image loadImage (String imagePath)
    {
        Image image = Toolkit.getDefaultToolkit().getImage(imagePath);
        return image;
    }
}
 
Habe swing benutzt und nun folgen Fehlermeldung: cannot find symbol - class Image
Es fehlt ein
Code:
import java.awt.Image;
Wie sollte ich denn das Bild Planet.png einbinden, um es nicht immer wieder neu zu laden?
Es geht nicht um das Planetenbild, das Vorgehen passt ja. Es geht um das Weltall.jpg. Das solltest Du nur einmalig im Konstruktor der Klasse laden - genauso wie Planet.png
 
Man darf nach wie vor
import java.awt.*;
schreiben, es geht nur um alles, was von "Component" erbt, also nicht Button, Label, Frame, sondern JButton, JLabel, JFrame verwenden - und man muss paintComponent statt paint überschreiben:
Java:
public class Man extends JComponent
{
    ...
    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);

        // BOGUS:
        Image Weltall = Toolkit.getDefaultToolkit().getImage("Weltall.jpg");
        g.drawImage(Weltall,0,0,this);
        g.drawImage(image, xPos, yPos, null);
    }
Bei jedem Neuzeichnen das Bild neu zu laden ist übrigens Unfug, wie schon gesagt wurde... glaub's oder glaub's nicht.

Und wichtig: Die Methode
Java:
/*
    public void setBounds(int x, int y)
    {
        xPos = x;
        yPos = y;
    }
*/
undbedingt umbennenen, auf jeden Fall nicht so implementieren: setBounds ist schon eine Methode in Component, d.h. dort überschreibst du die Original-setBounds-Methode - das kann einen Huafen Probleme verursachen!
 
Zusammengefasst so in etwa:
Java:
import java.io.*;
import java.awt.*;
import javax.swing.*;
import javax.imageio.*;

public class SpacePanel extends JPanel
{
    private Image spaceImage, planetImage;
    private int xPos, yPos;

    public SpacePanel(String imagePath, int x, int y)
    {
        spaceImage = loadImage("Weltall.jpg");
        planetImage = loadImage(imagePath);
        xPos = x;
        yPos = y;
        setBackground(Color.blue);
    }

    public void movePlanet(int x, int y)
    {
        xPos = x;
        yPos = y;
        repaint();
    }

    private Image loadImage(String imagePath)
    {
        try {
          return ImageIO.read(new File(imagePath));
        }
        catch(IOException e) {
          JOptionPane.showInternalMessageDialog(this,
          "Eine Grafikdatei konnte nicht geladen werden!",
          "IOException",
          JOptionPane.ERROR_MESSAGE);
        }
        return null;
    }

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        if(spaceImage != null && planetImage != null) {
            g.drawImage(spaceImage, 0, 0, this);
            g.drawImage(planetImage, xPos, yPos, this);
        }

    }
}
 

Zurück
Oben