Fehlverhalten einer Spielfigur

Jeff93

Mitglied
Hallo liebe Community,

ich habe vor kurzem mit der Java Programmierung begonnen und muss zugeben, dass mir die Sprache sehr gefällt, alles so schön OO. Ich habe mir jetzt sogar ein kleines Spiel programmiert. Im Spiel gibt es eine Figur die sich nach links und rechts bewegen muss um Rechtecken, die von oben herabfallen auszuweischen. Dies funktioniert soweit, doch ich habe das Gefühl dass sich die Spielfigur schneller nach links als nach rechts bewegt. Ich habe keinen Anhaltspunkt wieso.

Hier der Code:
Java:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.Vector;
import javax.swing.*;

public class MovableImage extends Rectangle  {
	
	/********************************************************************************************************
		VARIABLEN - DEKLARATION
	*********************************************************************************************************/
		
	protected int speedX=0;
	protected int speedY=0;
	
	protected JComponent jcomponent = null;
	protected BufferedImage Image=null;


	/********************************************************************************************************
		KONSTRUKTOREN
	*********************************************************************************************************/
	
	public MovableImage () { }
	
	public MovableImage (int x, int y, BufferedImage image,JComponent jp) {
		setJComponent(jp);
		setX(x);
		setY(y);
		setBufferedImage(image);
	}
	
	public MovableImage (int x, int y, int speedX, int speedY, BufferedImage image,JComponent jp) {
		this(x,y,image,jp);
		setSpeedX(speedX);
		setSpeedY(speedY);
		
	}
	
	
	/********************************************************************************************************
		SETTER - METHODEN
	*********************************************************************************************************/
	
	public void setJComponent (JComponent jp) {
		this.jcomponent = jp;
	}
	
	public void setY (int y) {
		this.y = y;
	}
	
	public void setX (int x) {
		this.x = x;
	}
	
	public void setBufferedImage (BufferedImage image) {
		this.Image = image;
		if (image!=null) {
			this.height = image.getHeight();
			this.width = image.getWidth();
		}
	}
	
	public void setSpeedX (int speedX) {
		this.speedX = speedX;
	}
	
	public void setSpeedY (int speedY) {
		this.speedY = speedY;
	}
	

	/********************************************************************************************************
		GETTER - METHODEN
	*********************************************************************************************************/
	
	public BufferedImage getBufferedImage () {
		return this.Image;
	}
	
	/********************************************************************************************************
		METHODEN
	*********************************************************************************************************/
	
	public void drawImage(Graphics g) {
		if (this.Image!=null && this.jcomponent!=null)
			g.drawImage(this.Image,this.x,this.y,this.jcomponent);
	}
	
	public void move (double delta) {
		if (speedX!=0)
			setX((int)(this.x+this.speedX*(delta/1e9)));
		if (speedY!=0)
			setY((int)(this.y+this.speedY*(delta/1e9)));
		
	}
	
}
Java:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.Vector;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.util.ArrayList;

public class GamePanel extends JPanel implements KeyListener,Runnable {

	/********************************************************************************************************
		VARIABLEN - DEKLARATION
	*********************************************************************************************************/

	boolean game_running;
	boolean game_over;
	
	private long delta;
	private long last;
	private long first;
	private long fps;
	private long seconds;
	private boolean new_sec;
	
	private int speedMarsMan;
	private int speedComet;
	private int speedCometInkr;

	
	private BufferedImage bg_img;
	
	private boolean left = false;
	private boolean right = false;
	
	private ArrayList<Comet> comets;
	
	protected MarsMan marsman = null;

	/********************************************************************************************************
		KONSTRUKTOREN
	*********************************************************************************************************/
	
	public GamePanel (int w, int h) {
		// set Dimensions of the Panel
		this.setPreferredSize(new Dimension(w,h));
		// create JFrame
		JFrame frame = new JFrame("the MarsMan");
		frame.setLocation(100,100);
		frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
		frame.add(this);
		frame.addKeyListener(this);
		frame.setResizable(false);
		// Adapt size of Frame to size of Panel
		frame.pack();
		frame.setVisible(true);
		// do Initializations
		doInit();
	}

	/********************************************************************************************************
		METHODEN
	*********************************************************************************************************/
	
	public static void main (String[] args) {
		GamePanel gamepanel = new GamePanel (300,300);
	}
	
	private void doInit () {
		BufferedImage marsman_img = (new BufferedImageLoader()).LoadImage("pics/MarsMan.gif");
		//
		first = last = System.nanoTime();
		delta = fps=seconds=delta=0;
		new_sec = game_over= left=right=false;		
		
		speedComet = 150;
		speedCometInkr = 20;
		speedMarsMan=100;
		
		bg_img = (new BufferedImageLoader()).LoadImage("pics/bgimg.jpg");
		comets = new ArrayList<Comet>();
		
		marsman = new MarsMan((int)((getWidth()-marsman_img.getWidth())/2), getHeight()-marsman_img.getHeight(),
			marsman_img,this);

		createComet();

		// start Thread
		game_running=true;
		Thread th = new Thread(this);
		th.start();
		
	}
	
	public void run () {
		// GameLoop
		while (game_running) {
			
			if (!game_over) {
				ComputeDelta ();
				CheckKeys();
				doLogic();
				Move();
			}
			repaint();
			try {
				Thread.sleep(10);
			} catch (InterruptedException ex) { }
		}
	}
	
	private void ComputeDelta () {
		long tmp;
		delta = System.nanoTime()-last;
		last = System.nanoTime();
		fps = ((long) (1e9))/delta;
		tmp=(System.nanoTime()-first)/((long) (1e9));
		new_sec = (tmp>seconds);
		seconds=tmp;
	}
	
	public void paintComponent (Graphics g) {
		super.paintComponent(g);
		if (game_running) {
			g.drawImage(bg_img,0,0,this);
			marsman.drawImage(g);
			for (Comet c :comets)
				c.drawImage(g);			
			if (game_over) {
				g.setColor(Color.red);
				g.setFont(new Font("",Font.BOLD,20));
				g.drawString("GAME OVER",50,100);
				g.setFont(new Font("",Font.BOLD,16));
				g.drawString("You survived "+seconds+" seconds",60,130);
				g.drawString("Klick ENTER to try again",70,150);
			}
			else {
			
			}
		}
	}

	private boolean CometsIntersecting (Comet com) {
		for (Comet c:comets)  {
			if (c.intersects(com))
				return true;
		}
		return false;
	}
	private void createComet () {
		BufferedImage tmp = (new BufferedImageLoader()).LoadImage(((int)(Math.random()*2))==1?"pics/comet1.gif":"pics/comet2.gif");		
		Comet c = new Comet((int)(Math.random()*(this.getWidth()-tmp.getWidth())), 1-tmp.getHeight(),
			0,speedComet,tmp,this);
		while (CometsIntersecting(c)) {
			c.setX((int)(Math.random()*(this.getWidth()-tmp.getWidth())));
		}
		comets.add(c);
	}
	
	private void doLogic () {
		// boost speed of comets
		if (seconds%3==0 && new_sec)
			speedComet+=speedCometInkr;
		if (seconds%8==0 && new_sec)
			createComet();
		
		
		for (int i=0;i<comets.size();++i) {
			if (!(comets.get(i)).intersects(this.getVisibleRect())) {
				comets.remove(i);
				createComet();
				--i;
			}
			else if ((comets.get(i)).intersects(marsman)) {
				game_over = true;
			}
		}
		
	}
	
	private void Move () {
		marsman.move(delta);
		for (Comet c:comets) {
			c.move(delta);
		}
	}
	
	private void CheckKeys () {
		if (right)
			marsman.setSpeedX(speedMarsMan);
		if (left)
			marsman.setSpeedX(-speedMarsMan);

		if (left==right)
			marsman.setSpeedX(0);
			
	}

	public void keyPressed(KeyEvent e) {
		
		if(e.getKeyCode()==KeyEvent.VK_A){
			left = true;
		}

		if(e.getKeyCode()==KeyEvent.VK_D){
			right = true;
		}
		
		if(e.getKeyCode()==KeyEvent.VK_ENTER && game_over){
			doInit();
		}
		
	}
		
	public void keyReleased(KeyEvent e) {
		

		if(e.getKeyCode()==KeyEvent.VK_A){
			left = false;
		}

		if(e.getKeyCode()==KeyEvent.VK_D){
			right = false;
		}
	
	}

	public void keyTyped(KeyEvent e) {

	}

}
Java:
import java.awt.image.BufferedImage;
import javax.swing.*;

public class MarsMan extends MovableImage {
	public MarsMan (int x, int y, BufferedImage image,JComponent jp) {
		super (x,y,image,jp);
	}
	
	/********************************************************************************************************
		SETTER - METHODEN
	*********************************************************************************************************/	
	public void setX (int x) {
		if (jcomponent==null || Image==null)
			this.x=x;
		else if (x<0)
			this.x = this.jcomponent.getWidth()-Image.getWidth();
		else if (x>=this.jcomponent.getWidth()-Image.getWidth())
			this.x = 0;
		else
			this.x = x;
	}
}
Wenn ihr keine Lust drauf habt euch das ganze Vieh herunterzuladen, könntet ihr mir ja eure Ideen posten.

Hoffe ihr könnt mir helfen, mfg, Jeff

PS: Die main ist in GamePanel, das Spiel wird gesteuert mit A und D
 
Zuletzt bearbeitet:

Empire Phoenix

Top Contributor
Hm, also gefühl habe ich auch, ja, zudem:
nach einmal sterben respawn, danach sind die Blöke nurnoch gefallen wenn ich eine taste gedrückt habe und ich konnte mich nicht mehr bewegen. Auf einen Blick kann ich dir allerdings nicht sagen, warum das so unterschiedlich schnell ist, aber:

Allerdings soweit wie ich das sehe sind 3 probleme vorhanden:
1. Du greifst direkt auf swing/awt Komponenten hinzu, das sollte man nicht tun wegen threadunsafe, gibt es ne relativ einfach Lösung aber da ich fast nie Swing benutze fällt mir der name nciht ein.
2. Du verlässt dich darauf, das dein Game immer gleich viele ms braucht für ein Frame. Stattdessen solltest du die wartezeit abhängig von der benötigte Zeit machen.
3. Du kannst dir wenn du dich auch eine fest Ticktime verlassen kannst eine Menge berechnungen sparen, weil du ja weißt wieviele ms vergangen sind und somit keine deltas berechnen musst (die oft genug Fehlerquellen darstellen können).
 

Quaxli

Top Contributor
Du solltest mit etwas größerer Genauigkeit rechnen, als mit int, dann geht's ;) (vgl. Tutorial, da wird auch Rectangle2D verwendet.

Dein Code oben hat bei mir funktioniert, nachdem ich folgende Änderungen eingebaut habe:

1. MarsMan erbt nicht mehr von Rectangle, sondern von Rectangle2D.Double
2. Anpassung der Move-Methode

Code:
	public void move (double delta) {
		if (speedX!=0){
			x = x+speedX*(delta/1e9);
		}
		
		if (speedY!=0){
			y = y+speedY*(delta/1e9);
		}
	}

Am Timer kann es nicht gelegen haben, da Du ja das Delta des Schleifendurchlaufs errechnest und die Figuren in Abhängigkeit davon bewegst. Von "auf gleichförmige Bewegung" verlassen, kann daher gar nicht die Rede sein.
Ursache war offensichtlich eine nicht ausreichend große Genauigkeit durch Rundungsfehler, die durch o. a. Modifikation beseitigt wird. Warum dies nur eine Richtung auftrat habe ich jetzt nicht genauer verfolgt.

2 Punkte noch, die ich persönlich als unschön empfinde:

1. Ich würde if-Bedingungen grundsätzlich mit geblockten Bedingunge versehen {}. Es erhöht sich die Lesbarkeit und reduziert mögliche Fehlerquellen.

2. Von diesen ganzen (imho unnötigen) this kriege ich Augenkrebs ;) Ich finde das nicht sehr lesbar - rein subjektiv gesehen. ;)
 

Jeff93

Mitglied
Du solltest mit etwas größerer Genauigkeit rechnen, als mit int, dann geht's ;) (vgl. Tutorial, da wird auch Rectangle2D verwendet.

Am Timer kann es nicht gelegen haben, da Du ja das Delta des Schleifendurchlaufs errechnest und die Figuren in Abhängigkeit davon bewegst. Von "auf gleichförmige Bewegung" verlassen, kann daher gar nicht die Rede sein.

Kann sein, denn als ich es mit den Timern versucht habe, habe ich das mit dem Delta sein gelassen.

Jeff

P.S: Gute Besserung Quaxli ^^
 

Empire Phoenix

Top Contributor
this is jetzt aber auch nicht schlecht, weil beim lesen dadurch auch eindeutig klar wird das es sich nicht um eine statische variable handelt. -> Tatsächlich schreibe ich sogar immer this hin wenns geht (hat auch den Vorteil das eclipse mir alle möglichen variablen anbietet ^^ und ich somit zeit spare wegen rechtschreibfehlern)

BTW hatte ich ja nicht ganz unrecht mit der Fehlerquelle der deltaberechnungen ^^
 

Quaxli

Top Contributor
this is jetzt aber auch nicht schlecht, weil beim lesen dadurch auch eindeutig klar wird das es sich nicht um eine statische variable handelt. -> Tatsächlich schreibe ich sogar immer this hin wenns geht (hat auch den Vorteil das eclipse mir alle möglichen variablen anbietet ^^ und ich somit zeit spare wegen rechtschreibfehlern)

Deswegen hatte ich auch hingeschrieben, daß ich das subjektiv sehe.

BTW hatte ich ja nicht ganz unrecht mit der Fehlerquelle der deltaberechnungen ^^

Doch.
Es ist ein Unterschied, ob es nicht da ist oder nur fehlerhaft.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
YangLee Ausgabe von einer Bewegung bei mehrzeiligen Strings Spiele- und Multimedia-Programmierung 1
E relevanter bereich einer isometrischen karte zeichnen (AffineTransform) Spiele- und Multimedia-Programmierung 0
M Audio Track einer Musik CD abspielen mittels vlcj-Bibliothek Spiele- und Multimedia-Programmierung 0
Meeresgott LWJGL 3 Problem mit einer Texture Spiele- und Multimedia-Programmierung 4
D Programmierung einer Tor-Anzeige Spiele- und Multimedia-Programmierung 8
C Optimale Wegberechnung einer KI Spiele- und Multimedia-Programmierung 6
T Pong Hilfe bei einer Website Spiele- und Multimedia-Programmierung 4
R Einfärben von Gemeinden auf einer Karte Spiele- und Multimedia-Programmierung 14
S ECS: "deep copy" einer Entity-Vorlage Spiele- und Multimedia-Programmierung 9
R Aufruf einer render-Methode Spiele- und Multimedia-Programmierung 12
E A-Stern Algorithmus Problem und Implementierung einer Map Spiele- und Multimedia-Programmierung 6
J Frage zum Einlesen einer .wav in ein byte Array Spiele- und Multimedia-Programmierung 3
J Spielfiguren laufen lassen auf einer html Tabelle mit Hilfe von Servlets Spiele- und Multimedia-Programmierung 2
T Alle Referenzen zu einer Klasse aus Java Bytecode ersetzt, JVM sucht trotzdem diese Klasse Spiele- und Multimedia-Programmierung 1
M Kamera "am Rande einer Kugel bewegen" Spiele- und Multimedia-Programmierung 4
B Den KeyListener in einer JavaFXML Application benutzen Spiele- und Multimedia-Programmierung 2
gamebreiti Index eines Elements einer ArrayList abfragen Spiele- und Multimedia-Programmierung 1
F Das sag mir einer Java ist plattform unabhänig ! Spiele- und Multimedia-Programmierung 10
M Scrolling einer 2D Map Spiele- und Multimedia-Programmierung 8
J In einer While-Schleife auf Event warten Spiele- und Multimedia-Programmierung 3
TheSorm Collision an einer bestimmten Seite eine Rectangles abfragen Spiele- und Multimedia-Programmierung 3
windl Frage zu Airplay und zur Mitarbeit bei einer Mediaanlage Spiele- und Multimedia-Programmierung 0
A Aufbau einer JOGL Anwendung Spiele- und Multimedia-Programmierung 12
L Werte aus einer .yml Datei lesen Spiele- und Multimedia-Programmierung 9
H Java3D - Textur aufs innere einer Sphere mappen Spiele- und Multimedia-Programmierung 9
F Download und Update einer Java-Anwendung Spiele- und Multimedia-Programmierung 10
D Problem beim bewegen einer Figur Spiele- und Multimedia-Programmierung 2
B Video von einer IP kamera Spiele- und Multimedia-Programmierung 5
W Java3D: Eckkoordinaten einer Box herausfinden Spiele- und Multimedia-Programmierung 18
W Rotation aller Objekte einer 3D-Szene Spiele- und Multimedia-Programmierung 8
2 Ein Zufallsweg bzw. Weg in einer 2dim Matrix finden. Spiele- und Multimedia-Programmierung 21
aze Schnittmenge zwischen Linie und einer Area wegschneiden Spiele- und Multimedia-Programmierung 3
A Bild einer Webcam auffangen Spiele- und Multimedia-Programmierung 20
G Ballerkennung aus einer Bilddatei Spiele- und Multimedia-Programmierung 24
B Generierung einer Wertetabelle aus einem Bild Spiele- und Multimedia-Programmierung 3
D Problem beim Öffnen einer PHP für eine Highscore Spiele- und Multimedia-Programmierung 5
M Realisierung einer Sichtweise in Java2D Spiele- und Multimedia-Programmierung 3
B String zu Objekt einer eigenen Klasse casten Spiele- und Multimedia-Programmierung 13
H Screenshot einer Graphics2D Anwendung erstellen Spiele- und Multimedia-Programmierung 6
F Simulation einer Magnetischen Flasche Spiele- und Multimedia-Programmierung 17
F Meine Aufgabe: Client-Server am Beispiel einer Implementation eines Tic-Tac-Toe Netzwerkspieles Spiele- und Multimedia-Programmierung 7
N Jogl Probleme mit dem Buffer beim laden einer Textur Spiele- und Multimedia-Programmierung 2
M Das Frequenzspektrum einer WAV/MP3-Datei anzeigen Spiele- und Multimedia-Programmierung 6
M Rechteck erkennung innerhalb einer Matix Spiele- und Multimedia-Programmierung 4
S Problem beim laden eines Bildes in einer Methode Spiele- und Multimedia-Programmierung 14
E Pinball Abprall an einer schrägen Bande Spiele- und Multimedia-Programmierung 19
0x7F800000 weiß einer wozu ANTLR beim build von JOGL verwendet wird? Spiele- und Multimedia-Programmierung 3
E Hilfe bei einer GUI Programmierung mit Graph Spiele- und Multimedia-Programmierung 30
A Tutorial für die Entwicklung einer Fussball-KI gesucht Spiele- und Multimedia-Programmierung 7
S Rotation relativ zur Rotation einer anderen Transform Group Spiele- und Multimedia-Programmierung 3
A Screenshots von einer Scene erstellen Spiele- und Multimedia-Programmierung 5
G Land aus einer Weltkarte selektieren Spiele- und Multimedia-Programmierung 10
D Kräftesimulation auf einer 2D-Oberfläche Spiele- und Multimedia-Programmierung 5
T Geschwindigkeit einer Animation aendern Spiele- und Multimedia-Programmierung 6
G Ermitteln eines Punktes in einer anderen TransformGroup Spiele- und Multimedia-Programmierung 2
N Background in Java3D ähnlich einer Skybox erzeugen Spiele- und Multimedia-Programmierung 5
H zB Punkte darstellen und mit einer Linier verbinden Spiele- und Multimedia-Programmierung 5
F Darstellung einer tierischen Zelle Spiele- und Multimedia-Programmierung 3
S Text an einer Seite eines Cubes Spiele- und Multimedia-Programmierung 7
F Das SPiel ruckelt nach einer Zeit Spiele- und Multimedia-Programmierung 19
D wieder einer von anfang an. Spiele- und Multimedia-Programmierung 4
M Darstellung einer schwingenden Membran? Spiele- und Multimedia-Programmierung 23
raptorrs Teile einer CAD-Assembly Gruppe in JAVA animieren? Spiele- und Multimedia-Programmierung 3
K Beschriftung von Punkten in einer "Punktwolke" Spiele- und Multimedia-Programmierung 2
S Zur Laufzeit auf die Methode einer anderen Klasse zugreifen Spiele- und Multimedia-Programmierung 5
K Klick in der nähe einer Strecke Spiele- und Multimedia-Programmierung 14
S gekillte Spielfigur Spiele- und Multimedia-Programmierung 5
M Fehlende Spielfigur auf neuer Landschaft Spiele- und Multimedia-Programmierung 2
A Spielfigur mit vielen Aktionen Spiele- und Multimedia-Programmierung 7
F RPG - Spielfigur soll sich nicht frei bewegen können. Anregugen wären gerne gesehen^^ Spiele- und Multimedia-Programmierung 13
A Spielfigur steuern Spiele- und Multimedia-Programmierung 8
G Bewegungen von Spielfigur Spiele- und Multimedia-Programmierung 2
M Bomberman: Bewegung der Spielfigur in windows viel schneller Spiele- und Multimedia-Programmierung 12

Ähnliche Java Themen

Neue Themen


Oben