Java Spiel Figur auf dem Hintergrundbild bewegen.

Nenad2001

Mitglied
Java:
package Paket;

import java.awt.Color;
import java.awt.Font;
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 java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Timer;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Spiel_Frame extends JFrame implements  ActionListener{

    JPanel panel_Rechteck;
    JPanel panel_Fläche;
    
    Point p_rect;
    Point p_fläche;
    
 
 
    
    final int WITDH = 1100;
    final int HEIGHT = 500;
    ImageIcon image;

    Image image2;
    

    
    public void paint(Graphics g) {
          
          Graphics2D g2D = (Graphics2D) g;

          image2 = new ImageIcon("Forest1.jpg").getImage();
          g2D.drawImage(image2 , -210, -230, this);

    
     }
    
public Spiel_Frame() {
    
this.setSize(WITDH, HEIGHT);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setLayout(null);
this.setTitle("2D Spiel");

ImageIcon image = new ImageIcon("2D bild.jpeg");
this.setIconImage(image.getImage());
    
panel_Rechteck = new JPanel();
panel_Rechteck.setOpaque(true);
panel_Rechteck.setBackground(Color.black);
panel_Rechteck.setBounds(450 ,50 , 50, 50);
    
    this.add(panel_Rechteck);
    
    panel_Fläche = new JPanel();
    panel_Fläche.setOpaque(true);
    panel_Fläche.setBackground(Color.black);
    panel_Fläche.setBounds(150 , 300 , 600 , 50);
        
 
        
        
        
        

        
        
 this.setVisible(true);   
}

@Override
public void actionPerformed(ActionEvent e) {
    

    
}

    


























}
Hey Leute Ich wollte jetzt mal fragen wie ich jetzt am besten meine Figur auf den gezeichneten Hintergrundbild einfüge und sie steure, weil wenn ich das mit einem Panel mache, radiert die Figur quasi das Hintergrundbild weg.
 
Hey Leute Ich wollte jetzt mal fragen wie ich jetzt am besten meine Figur auf den gezeichneten Hintergrundbild einfüge und sie steure, weil wenn ich das mit einem Panel mache, radiert die Figur quasi das Hintergrundbild weg.
Wie @Apple’s Jünger richtig bemerkt hat musst du die gesamte Szene immer wieder neu zeichnen.
Wenn ich das richtig sehe, möchtest Du ein Spiel programmieren.
Das bedeutet du möchtest Figuren bewegen und diese interagieren lassen.
Daraus lassen sich 2 verschiedene Objekte ableiten.
1) Die Figur
Eine kleine bewegte Grafik nennt man Sprite.
Sie benötigt Eigenschaften wie folgt.
Position, Richtung, Geschwindigkeit usw.
2) Die Welt ( worin die Figuren leben )

In der Welt läuft eine Dauerschleife
solange( Spiel läuft ){
ändere die Positionen, Zustand der Figuren, reagiere auf Eingaben des Spielers usw.
zeichne alles neu
warte ein wenig
}

also in etwa so
while(running){
update()
render()
sleep()
}


Angenommen du hast dir eine Klasse Sprite für die Figur und eine Klasse GamePanel für die Welt gemacht.
Dann könnte man folgenden Code für bewegte Sprites schreiben.
Java:
import javax.swing.JFrame;

[B]StartMoveSprite[/B]
Erzeugt das Fenster das Spiel beinhaltet und startet es.
public class StartMoveSprite {
    public static void main(String[] args) {
        Game game = new Game(600, 600);
        JFrame frame = new JFrame("Move a Sprite");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(game);
        frame.pack();
        frame.setResizable(false);
        frame.setVisible(true);
        game.start();
    }
}

Game
erweitert die Klasse GamePanel und überschreibt die Methoden
render( Graphics g ) und update() für die Spielschleife des GamePanel.

Es werden 4 Sprites in der Welt mit unterschiedlichen Geschwindigkeiten und Richtungen erzeugt und bewegt.
Du kannst Dir zum Testen die moveSprite.jar herunterladen.
Falls Du die Klasse Sprite und GamePanel sehen willst, kann ich sie hier auch posten.
Auch Fragen zum Code kannst Du hier stellen.


Java:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;

@SuppressWarnings("serial")
public class Game extends GamePanel {
    private Sprite[] sprite = new Sprite[4];

    public Game(int width, int height) {
        super(width, height);
        initGame();
    }

    public void initGame() {
        Color color = Color.BLUE.brighter();
        int size = 30;
        int x = 100;
        int y = 50;
        float angle = 45;
        float speed = 1.5f;
        for (int i = 0; i < sprite.length; i++) {
            sprite[i] = new Sprite(size, size);
            sprite[i].setPosition(x, y);
            sprite[i].setDirection(angle);
            sprite[i].setColor(color);
            sprite[i].setSpeed(speed);
            color = color.darker();
            size += 5;
            x += 100;
            y += 40;
            angle += 33;
            speed += .6f;
        }
    }

    private void drawBackGround(Graphics2D g) {
        int width = getWidth();
        int height = getHeight();
        Color color = getBackground();
        int num = 10;
        float step = width / num;
        Rectangle2D.Float rect = new Rectangle2D.Float(0, 0, step, height);
        for (int i = 0; i < num; i++) {
            g.setColor(color);
            g.fill(rect);
            rect.x += step;
            color = color.darker();
        }
    }

    @Override
    protected void render(Graphics2D g) {
        drawBackGround(g);
        for (Sprite s : sprite)
            s.draw(g);
    }

    @Override
    protected void update() {
        Rectangle bound = getBounds();
        for (Sprite s : sprite) {
            s.move();
            s.reflectAtBounds(bound);
        }

    }

}
 

Anhänge

Wie @Apple’s Jünger richtig bemerkt hat musst du die gesamte Szene immer wieder neu zeichnen.
Wenn ich das richtig sehe, möchtest Du ein Spiel programmieren.
Das bedeutet du möchtest Figuren bewegen und diese interagieren lassen.
Daraus lassen sich 2 verschiedene Objekte ableiten.
1) Die Figur
Eine kleine bewegte Grafik nennt man Sprite.
Sie benötigt Eigenschaften wie folgt.
Position, Richtung, Geschwindigkeit usw.
2) Die Welt ( worin die Figuren leben )

In der Welt läuft eine Dauerschleife
solange( Spiel läuft ){
ändere die Positionen, Zustand der Figuren, reagiere auf Eingaben des Spielers usw.
zeichne alles neu
warte ein wenig
}

also in etwa so
while(running){
update()
render()
sleep()
}


Angenommen du hast dir eine Klasse Sprite für die Figur und eine Klasse GamePanel für die Welt gemacht.
Dann könnte man folgenden Code für bewegte Sprites schreiben.
Java:
import javax.swing.JFrame;

[B]StartMoveSprite[/B]
Erzeugt das Fenster das Spiel beinhaltet und startet es.
public class StartMoveSprite {
    public static void main(String[] args) {
        Game game = new Game(600, 600);
        JFrame frame = new JFrame("Move a Sprite");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(game);
        frame.pack();
        frame.setResizable(false);
        frame.setVisible(true);
        game.start();
    }
}

Game
erweitert die Klasse GamePanel und überschreibt die Methoden
render( Graphics g ) und update() für die Spielschleife des GamePanel.

Es werden 4 Sprites in der Welt mit unterschiedlichen Geschwindigkeiten und Richtungen erzeugt und bewegt.
Du kannst Dir zum Testen die moveSprite.jar herunterladen.
Falls Du die Klasse Sprite und GamePanel sehen willst, kann ich sie hier auch posten.
Auch Fragen zum Code kannst Du hier stellen.


Java:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;

@SuppressWarnings("serial")
public class Game extends GamePanel {
    private Sprite[] sprite = new Sprite[4];

    public Game(int width, int height) {
        super(width, height);
        initGame();
    }

    public void initGame() {
        Color color = Color.BLUE.brighter();
        int size = 30;
        int x = 100;
        int y = 50;
        float angle = 45;
        float speed = 1.5f;
        for (int i = 0; i < sprite.length; i++) {
            sprite[i] = new Sprite(size, size);
            sprite[i].setPosition(x, y);
            sprite[i].setDirection(angle);
            sprite[i].setColor(color);
            sprite[i].setSpeed(speed);
            color = color.darker();
            size += 5;
            x += 100;
            y += 40;
            angle += 33;
            speed += .6f;
        }
    }

    private void drawBackGround(Graphics2D g) {
        int width = getWidth();
        int height = getHeight();
        Color color = getBackground();
        int num = 10;
        float step = width / num;
        Rectangle2D.Float rect = new Rectangle2D.Float(0, 0, step, height);
        for (int i = 0; i < num; i++) {
            g.setColor(color);
            g.fill(rect);
            rect.x += step;
            color = color.darker();
        }
    }

    @Override
    protected void render(Graphics2D g) {
        drawBackGround(g);
        for (Sprite s : sprite)
            s.draw(g);
    }

    @Override
    protected void update() {
        Rectangle bound = getBounds();
        for (Sprite s : sprite) {
            s.move();
            s.reflectAtBounds(bound);
        }

    }

}
danke dir ich werde das gleich mal ausprobieren wenn ich eine frage habe stelle ich sie dir würde aber gerne die anderen klassen sehen die du vorgeschlagen hast 🙂
 
danke dir ich werde das gleich mal ausprobieren wenn ich eine frage habe stelle ich sie dir würde aber gerne die anderen klassen sehen die du vorgeschlagen hast
Java:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JComponent;

@SuppressWarnings("serial")
public abstract class GamePanel extends JComponent implements Runnable {
    private boolean running = false;
    private Thread animator;

    public GamePanel(int width, int height) {
        setPreferredSize(new Dimension(width, height));
    }

    @Override
    protected final void paintComponent(Graphics g) {
        super.paintComponent(g);
        render((Graphics2D) g);
    }

    /**
     * Do drawing stuff here.
     *
     * @param g
     */
    protected abstract void render(Graphics2D g);

    @Override
    public void run() {
        while (running) {
            try {
                update();
                repaint();
                Thread.sleep(9);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void start() {
        stop();
        animator = new Thread(this);
        running = true;
        animator.start();
    }

    public void stop() {
        running = false;
        while (animator != null && animator.isAlive())
            ;
        animator = null;
    }

    /**
     * Do game logic here
     */
    protected abstract void update();

}

Java:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;

public class Sprite {
    public final static int NOT_HIT = 0;
    public final static int TOP_HIT = 1;
    public final static int RIGHT_HIT = 2;
    public final static int BOTTOM_HIT = 4;
    public final static int LEFT_HIT = 8;

    protected float dx = 0; // direction x
    protected float dy = 0; // direction y
    protected float speed = 0; // speed
    protected float x = 0; // position x
    protected float y = 0; // position x
    private Color color = Color.WHITE;
    private Rectangle bounds; // bounding box

    public Sprite(int width, int height) {
        bounds = new Rectangle(0, 0, width, height);
    }

    public void draw(Graphics g) {
        g.setColor(color);
        g.fillRect((int) x, (int) y, bounds.width, bounds.height);
    }

    public Rectangle getBoundingBox() {
        bounds.x = (int) x;
        bounds.y = (int) y;
        return bounds;
    }

    private double getDirection() {
        double angle = Math.toDegrees(dx != 0 ? Math.acos(dx) : Math.asin(dy));
        return (dy < 0) ? 360 - angle : Math.round(angle);
    }

    public float getHeight() {
        return bounds.height;
    }

    public float getSpeed() {
        return speed;
    }

    public float getWidth() {
        return bounds.width;
    }

    public float getX() {
        return x;
    }

    public float getY() {
        return y;
    }

    public boolean isCollision(Sprite s) {
        return s.getBoundingBox().intersects(getBoundingBox());
    }

    public void invertDirX() {
        dx = -dx;
    }

    public void invertDirY() {
        dy = -dy;
    }

    public void invertDir() {
        invertDirX();
        invertDirY();
    }

    public void move() {
        x += dx * speed;
        y += dy * speed;
    }

    public int reflectAtBounds(Rectangle bound) {
        if (bound == null || bound.width <= 0 || bound.height <= 0)
            return NOT_HIT;
        int hit = NOT_HIT;

        if (x < bound.x) {
            x = bound.x;
            hit = LEFT_HIT;
        } else if (x > bound.x + bound.width - getWidth()) {
            x = bound.x + bound.width - getWidth();
            hit |= RIGHT_HIT;
        }
        if (y < bound.y) {
            y = bound.y;
            hit |= TOP_HIT;
        } else if (y > bound.y + bound.height - getHeight()) {
            y = bound.y + bound.height - getHeight();
            hit |= BOTTOM_HIT;
        }
        if ((hit & RIGHT_HIT + LEFT_HIT) != NOT_HIT)
            invertDirX();
        if ((hit & BOTTOM_HIT + TOP_HIT) != NOT_HIT)
            invertDirY();
        return hit;
    }

    public void setColor(Color color) {
        this.color = color;
    }

    public void setDirection(float angle) {
        float alpha = (float) Math.toRadians(angle);
        dx = (float) Math.cos(alpha);
        dy = (float) -Math.sin(alpha);
    }

    public void setPosition(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public void setSpeed(float speed) {
        this.speed = speed;
    }

    @Override
    public String toString() {
        return String.format("[%.2f,%.2f]-> %.2f", x, y, getDirection());
    }

}
 
Java:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JComponent;

@SuppressWarnings("serial")
public abstract class GamePanel extends JComponent implements Runnable {
    private boolean running = false;
    private Thread animator;

    public GamePanel(int width, int height) {
        setPreferredSize(new Dimension(width, height));
    }

    @Override
    protected final void paintComponent(Graphics g) {
        super.paintComponent(g);
        render((Graphics2D) g);
    }

    /**
     * Do drawing stuff here.
     *
     * @param g
     */
    protected abstract void render(Graphics2D g);

    @Override
    public void run() {
        while (running) {
            try {
                update();
                repaint();
                Thread.sleep(9);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void start() {
        stop();
        animator = new Thread(this);
        running = true;
        animator.start();
    }

    public void stop() {
        running = false;
        while (animator != null && animator.isAlive())
            ;
        animator = null;
    }

    /**
     * Do game logic here
     */
    protected abstract void update();

}

Java:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;

public class Sprite {
    public final static int NOT_HIT = 0;
    public final static int TOP_HIT = 1;
    public final static int RIGHT_HIT = 2;
    public final static int BOTTOM_HIT = 4;
    public final static int LEFT_HIT = 8;

    protected float dx = 0; // direction x
    protected float dy = 0; // direction y
    protected float speed = 0; // speed
    protected float x = 0; // position x
    protected float y = 0; // position x
    private Color color = Color.WHITE;
    private Rectangle bounds; // bounding box

    public Sprite(int width, int height) {
        bounds = new Rectangle(0, 0, width, height);
    }

    public void draw(Graphics g) {
        g.setColor(color);
        g.fillRect((int) x, (int) y, bounds.width, bounds.height);
    }

    public Rectangle getBoundingBox() {
        bounds.x = (int) x;
        bounds.y = (int) y;
        return bounds;
    }

    private double getDirection() {
        double angle = Math.toDegrees(dx != 0 ? Math.acos(dx) : Math.asin(dy));
        return (dy < 0) ? 360 - angle : Math.round(angle);
    }

    public float getHeight() {
        return bounds.height;
    }

    public float getSpeed() {
        return speed;
    }

    public float getWidth() {
        return bounds.width;
    }

    public float getX() {
        return x;
    }

    public float getY() {
        return y;
    }

    public boolean isCollision(Sprite s) {
        return s.getBoundingBox().intersects(getBoundingBox());
    }

    public void invertDirX() {
        dx = -dx;
    }

    public void invertDirY() {
        dy = -dy;
    }

    public void invertDir() {
        invertDirX();
        invertDirY();
    }

    public void move() {
        x += dx * speed;
        y += dy * speed;
    }

    public int reflectAtBounds(Rectangle bound) {
        if (bound == null || bound.width <= 0 || bound.height <= 0)
            return NOT_HIT;
        int hit = NOT_HIT;

        if (x < bound.x) {
            x = bound.x;
            hit = LEFT_HIT;
        } else if (x > bound.x + bound.width - getWidth()) {
            x = bound.x + bound.width - getWidth();
            hit |= RIGHT_HIT;
        }
        if (y < bound.y) {
            y = bound.y;
            hit |= TOP_HIT;
        } else if (y > bound.y + bound.height - getHeight()) {
            y = bound.y + bound.height - getHeight();
            hit |= BOTTOM_HIT;
        }
        if ((hit & RIGHT_HIT + LEFT_HIT) != NOT_HIT)
            invertDirX();
        if ((hit & BOTTOM_HIT + TOP_HIT) != NOT_HIT)
            invertDirY();
        return hit;
    }

    public void setColor(Color color) {
        this.color = color;
    }

    public void setDirection(float angle) {
        float alpha = (float) Math.toRadians(angle);
        dx = (float) Math.cos(alpha);
        dy = (float) -Math.sin(alpha);
    }

    public void setPosition(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public void setSpeed(float speed) {
        this.speed = speed;
    }

    @Override
    public String toString() {
        return String.format("[%.2f,%.2f]-> %.2f", x, y, getDirection());
    }

}
Danke dir echt korrekt von dir 🙂
 
1) Die Figur
Eine kleine bewegte Grafik nennt man Sprite.
Nur ein kleiner Klugscheißereinwurf. So ist das eigentlich nicht richtig.
Der Sinn und Zweck von Sprites ist, dass man eben nicht den gesamten Hintergrund neu zeichnen muss.
Sprites sind Grafiken, die direkt in den Grafikbuffer gezeichnet wurden, die unabhängig vom ganzen Rest dahinter funktionieren und je nach System bis zu 16 Pixel breit (üblicherweise 8 Pixel auf einem 8 Bit System, 16 Pixel auf einem 16 Bit System, aber da mag es Abweichungen geben). Man kann z.B. mit einem Sprite einen Mauszeiger in einem Texteditor sehr kostengünstig umsetzen. Ein System konnte auch nur eine begrenzte Anzahl an Sprites behandeln, üblicherweise ebenfalls bis zu 16. Mario bestand z.B. aus 4 Sprites (er konnte ja größer werden, war also nicht in einem Sprite darstellbar), es blieben also noch reichlich Sprites für die Gegner übrig.
Aber schon damals verwendeten nicht alle Spiele Sprites für die Spielfiguren. Am Amiga gab es z.B. Befehle, um Grafiken (auch große) schnell verschieben zu können, Sprites waren deshalb schlicht und einfach nicht notwendig, also verzichtete man darauf. Schließlich sind sie etwas umständlich zu handhaben, sie existieren in der gezeichneten Grafik eigentlich gar nicht, sondern nur im Buffer, welcher direkt an den Bildschirm geht.
Auf modernen Systemen sind Sprites (so gut wie?) ausgestorben, die Generierung eines kompletten Spiels geht so schnell, dass es dafür keine Verwendung mehr gibt.

Der technische Hintergrund interessiert aber kaum jemanden, deshalb wird der Begriff Sprite auch oft für die Grafik selbst verwendet und nicht für die Methode, wie sie auf den Bildschirm kommt, auch wenn das nicht richtig ist.

Aber der Rest .... top 😀

ps: Recht interessant
Hier wurde die Technologie hinter Risky Woods zerlegt, welches extrem auf Sprites setzt, sogar das Parallax-Scrolling im Hintergrund damit umsetzt (die Amiga Sprites konnten über die gesamte Bildschirmhöhe gehen).
 
Zuletzt bearbeitet:
Nur ein kleiner Klugscheißereinwurf. So ist das eigentlich nicht richtig.
Der Sinn und Zweck von Sprites ist, dass man eben nicht den gesamten Hintergrund neu zeichnen muss.
Danke das ist mir bekannt, da ich in den frühen 80ern mit echten Sprites (Hardware) auf dem Commodore 64 meine ersten kleinen Spiele programmiert habe. Das war Anfangs mit Basic. Durch pokes konnte man bis zu 8 Sprites an-, ausschalten bewegen usw.
(Durch Tricks mit dem Interrupt Pointer konnte man auch noch mehr benutzen )
Da Basic bei nicht einmal 1 MHz Takt des Prozessors 6510 etwas langsam war, machte ich mit Maschinensprache weiter. Anfangs nur mit einem einfachen in Basic selbst geschrieben Monitorprogramm, später mit einer Steckkarte und einem von einem Freund selbst geschriebenen Assembler. Seitdem verwende ich den Begriff Sprite, der übersetzt Kobold oder Elfe bedeutet, für eine bewegte Grafik in meinen Programmen.

Durch das Arbeiten mit den begrenzten Resourcen 64kb Ram habe ich sehr viel über das Programmieren gelernt. Die gängige Ausrede für viele heutige Programmierer, sich darum nicht kümmern zu müssen da das alles der Compiler macht, teile ich nur bedingt.
Aber dein Einwurf, dass der eigentliche Sinn von Sprites war, zu vermeiden den gesamten Hintergrund, immer wieder zeichnen zu müssen stimmt. 😉
 
Zuletzt bearbeitet:

Zurück
Oben