Rennspiel - Bildschirm auf Spielerauto zentrieren

Kloser1911

Grünschnabel
Ersteinmal ein kleines Hallo, bin ja noch neu hier um euch direkt mit einem Problem zu belästigen.

Nachdem wir in der Schule vor mehreren Wochen mit der Programmiersprache Java, aber nur mit der "Stift und Maus" Bibliothek des MG-Werl, angefangen haben, dürfen wir uns unser letztes Projekt in diesem Schuljahr selber auszudenken und entwerfen. Da jedoch wie ich finde die SuM Bibliothek einem von Java nur wenig beibringt, will ich dieses mal ohne sie programmieren, weshalb ich schon mehrere Tutorials gelesen habe.

Jedenfalls habe ich angefangen ein 2d Rennspiel mit einer Vogelansicht von Oben zu programmieren, wobei sich im moment das Objekt der Klasse Auto bewegt und die Strecke/der Hintergrund (dieses ist bisjetzt nur ein Bild) nicht... nun möchte ich jedoch, das das Auto im Zentrum des Bildschirms ist und sich der Hintergrund bewegt, wozu ich jedoch keinen für mich verständlichen Ansatz finde.

Hier einmal mein bisheriger Code:

Meine Klasse zum ausführen des Programmes:
Java:
import javax.swing.JFrame;
import java.awt.image.BufferStrategy;

public class CarRPG extends JFrame {

    public CarRPG() {

        add(new Spielfeld());

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(1280,800);
        setLocationRelativeTo(null);
        setTitle("CarRPG");
        setResizable(true);
        setVisible(true);
        
    }

    public static void main(String[] args) {
        new CarRPG();

    }
}

Die Klasse Auto (die //Kommentierung ist nur für unseren Lehrer, da diese verlangt ist):
Java:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.AffineTransformOp;
import java.awt.geom.*;
import javax.sound.sampled.*;
import javax.sound.*;
import java.applet.*;
import java.io.*;
import java.net.*;
import javax.swing.*;

public class Auto
{

    private double dx;//deltax gibt die Veränderung der X Koordinate des Autos an
    private double dy;//deltay gibt die Veränderung der Y Koordinate des Autos an
    private double x;//Aktuelle X-Koordinate des Autos (wird im Hauptprogramm benötigt)
    private double y;//Aktuelle Y-Koordinate des Autos (wird im Hauptprogramm benötigt)
    private double winkel;//drehung des Autos
    private Image image;//Bild(Sprite) welches das Auto widerspigelt
    private String auto = "auto.gif";//dient als URL zum Bild des Autos
    private double v;//Geschwindigkeit
    private boolean drehelinks;//Abfrage ob nach links gelenkt werden soll
    private boolean dreherechts;//Abfrage ob nach rechts gelenkt werden soll
    private boolean beschleunigen;//Abfrage ob nach beschleunigt werden soll
    private boolean bremsen;//Abfrage ob gebremst werden soll
    private double vmax;//höchstgeschwindigkeit des Autos in pixel
    private double handling;//Lenkeinschlag des Autos in °
    private double beschleunigung;//beschleunigung des Autos in pixel
    private double bremsbeschleunigung;//bremsbeschleunigung des Autos in pixel
    private double trägheit;//Faktor mit dem das Auto abbremst
    private double vmaxrückwärts;//höchstgeschwindigkeit beim rückwärtsfahren

    public Auto()
    {
        ImageIcon ii = new ImageIcon(this.getClass().getResource(auto));//das Bild wird geladen
        image = ii.getImage();//

        x = 500;//Startkoordinaten des Autos
        y = 500;//
        winkel = 0;//Anfangswinkel
        v = 0;//Anfangsgeschwindigkeit
        vmax = 5;//deklarieren der Variablen, welche das Fahrverhalten bestimmen
        vmaxrückwärts = -1;//
        handling = 3;//
        beschleunigung = 0.15;//
        bremsbeschleunigung = 0.2;//
        trägheit = 0.997;//
    }

    public void winkel()//veränderung der X und Y Koordinaten wird bestimmt
    {
        dx = Math.cos(Math.toRadians(winkel)) * v;//DeltaX = cos^-1(winkel)*geschwindigkeit(Hypothenuse)
        dy = Math.sin(Math.toRadians(winkel)) * v;//DeltaY = sin^-1(winkel)*geschwindigkeit(Hypothenuse)
    }

    public void bewegen()//das Auto wird bewegt
    {
        dx = Math.cos(Math.toRadians(winkel)) * v;//DeltaX = cos^-1(winkel)*geschwindigkeit(Hypothenuse)
        dy = Math.sin(Math.toRadians(winkel)) * v;//DeltaY = sin^-1(winkel)*geschwindigkeit(Hypothenuse)

        if (drehelinks == true)
        {
            if (dx != 0 || dy != 0)
            {
                if (winkel == 0)
                    winkel = 360;
                if (v > 0)
                    winkel = winkel - handling*(v/vmax);
                else
                    winkel = winkel - handling*(v/vmax);
            }
        }

        if (dreherechts == true)
        {
            if (dx != 0 || dy != 0)
            {   
                if (winkel == 360)
                    winkel = 0;
                if (v > 0)
                    winkel = winkel + handling*(v/vmax);
                else
                    winkel = winkel + handling*(v/vmax);
            }
        }
        if (beschleunigen == true)
        {
            if (v < vmax)
                v +=  beschleunigung;
        }
        if (bremsen == true)
        {
            if (v > vmaxrückwärts)
            {
                if (v < vmaxrückwärts)
                    v -=  beschleunigung;
                else 
                    v -=  bremsbeschleunigung;
            }
        }
        if (bremsen == false && beschleunigen == false)
        {
            v = v * trägheit;
        }

        x += dx;
        y += dy;
    }

    public int getX()//die X Koordinate wird abgerufen
    {
        return (int) StrictMath.round(x);
    }

    public int getY()//die Y-Koordinate wird abgerufen
    {
        return (int) StrictMath.round(y);
    }

    public Image getImage()//das Bild des Autos wird abgerufen
    {
        return image;
    }

    public void keyPressed(KeyEvent e)//ereignisse, welche beim drücken bestimmter Tasten hervorgerufen wird
    {

        int key = e.getKeyCode();

        if (e.getKeyCode() == KeyEvent.VK_LEFT)
        {
            drehelinks = true;
        }

        if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
            dreherechts = true;
        }

        if (e.getKeyCode() == KeyEvent.VK_UP) {
            beschleunigen = true;
        }

        if (e.getKeyCode() == KeyEvent.VK_DOWN) {
            bremsen = true;

        }

    }

    public void keyReleased(KeyEvent e)//ereignisse, welche beim loslassen bestimmter Tasten hervorgerufen wird

    {
        int key = e.getKeyCode();

        if (e.getKeyCode() == KeyEvent.VK_LEFT)
        {
            drehelinks = false;
        }

        if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
            dreherechts = false;
        }

        if (e.getKeyCode() == KeyEvent.VK_UP) {
            beschleunigen = false;
        }

        if (e.getKeyCode() == KeyEvent.VK_DOWN) {
            bremsen = false;
        }
    }

    public void zeichnen(Graphics g)
    {
        Graphics2D g2d = (Graphics2D)g;

        AffineTransform af = g2d.getTransform();

        double centerx,centery;

        centerx = Math.cos(Math.toRadians(winkel))*10;
        centery = Math.sin(Math.toRadians(winkel))*43;

        g2d.rotate(Math.toRadians(winkel+90),x,y);

        g2d.drawImage(this.getImage(), this.getX(), this.getY(),null );

        g2d.setTransform(af);

    }
}


Und mein Spielfeld:
Java:
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import javax.swing.*;

public class Spielfeld extends JPanel implements ActionListener {

    private Timer timer;
    private Auto auto;

    public static int wartezeit = 1000/60;
    
    Image hintergrund;

    public Spielfeld() {
        ImageIcon ii = new ImageIcon(this.getClass().getResource("hintergrund.gif"));
        hintergrund = ii.getImage();
        addKeyListener(new TAdapter());
        setFocusable(true);
        
        setDoubleBuffered(true);

        auto = new Auto();

        timer = new Timer(wartezeit, this);
        timer.start();
    }

    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.drawImage(hintergrund, 10, 10, null);
        auto.zeichnen(g);
        Toolkit.getDefaultToolkit().sync();
        g.dispose();
    }

    public void actionPerformed(ActionEvent e)
    {
        auto.bewegen();
        repaint();
        timer.setRepeats(true);
        timer.start();

    }

    private class TAdapter extends KeyAdapter {

        public void keyReleased(KeyEvent e) {
            auto.keyReleased(e);
        }

        public void keyPressed(KeyEvent e) {
            auto.keyPressed(e);
        }
    }

}

Desweiteren ist noch anzumerken das der Hintergrund enorm flackert, wobei ich auch hier nicht die Gründe dafür kenne, unseren Lehrer kann ich leider nicht fragen da er bei Problemen nur auf Fehlermeldungen hinweist (wobei ja eigentlich garkeine entsteht).

Nunja, wenn jemand die Zeit findet mir zu helfen kann ich erstmal nur Danke sagen, bis später.
 
Zuletzt bearbeitet:
Hallo
erst mal allgemein: den Code bitte in java-Tags, dann kann man ihn besser lesen (siehe meine Signatur).
Zu den Kommentaren: Das ist doch gut, dass du so viel kommentierst! Bei größeren Softwareprojekten gilt die Faustregel, dass der Code nur dann gut zu warten und wiederverwenden ist, wenn mehr (aussagekräftige) Kommentare als Code vorhanden sind.

Eine Anregung:
Prinzipiell ist es üblich, dass du statische Objekte durch Zeichnen in die höhere Ebene realisierst. In deinem Fall könnte man also nur den Hintergrund bewegt, das Auto aber gar nicht. Der Hintergrund wird dann einfach umgekehrt zur Bewegungsrichtung gedreht, d.h.:
statt das Auto nach links zu drehen, wird der Hintergrund nach rechts gedreht.
statt das Auto nach vorne(oben) zu bewegen, wird der Hintergrund nach hinten(unten) bewegt.

In deinem Code habe ich einen Fehler gefunden: Bei graphischen Komponenten des Pakets javax.swing (z.B. JPanel, JComponent, JButton, JFrame, ...) sollte man nicht die paint()-Methode überschreiben (wie du es getan hast), sondern stattdessen die paintComponent()-Methode. Dies kann die Ursache für das von dir beobachtete Flackern sein. Außerdem sollte man zu Beginn dieser Methode dann auch super.paintComponent() aufrufen oder wenigstens die komplette Fläche übermalen, wie du es in der paint()-Methode schon gemacht hast.

EDIT: du solltest nicht die Methode dispose() vor Graphics aufrufen. Das steht auch so in der JavaDoc: http://download.oracle.com/javase/6/docs/api/java/awt/Graphics.html#dispose()
 
Zuletzt bearbeitet:
Zurück