Wackelige Angelegenheit

Androbin

Bekanntes Mitglied
Hallo Leute, ich habe hier einige Probleme:
Ich bin gerade dabei, "MinePlex" zu programmieren, eine 2D-Nachmache von Minecraft!
Die Probleme sind, dass der Spieler flimmert, die gesammte Welt, wenn sich der Spieler bewegt, verschoben überlappt, d.h., es werden Blocks gezeichnet, wo keine sind, ... !

Hier der Quellcode: ( workspace im Anhang! )

Der MainFrame:
Java:
package net.diegamingbrueder.games.MinePlex;

import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;

public class MainFrame extends JFrame implements ActionListener {
	
	// Deklarationen
	
    private static final long serialVersionUID = 1L;
    
	public static JFrame frame;
	public static Credits credits;
	public static JButton BPlay, BCredits, BExit;
	
	public static World world;
	
	// Konstruktoren
	
    public MainFrame() {
		
		// Frame erzeugen
		
		super( "MinePlex" );
		setSize( 200, 200 );
		setResizable( false );
		setLocationRelativeTo( null );
		setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
		setIconImage( Toolkit.getDefaultToolkit().getImage( "res/MinePlex/icon.png" ) );
		
		try { setCursor( Toolkit.getDefaultToolkit().createCustomCursor( ImageIO.read( new File( "res/MinePlex/cursor.png" ) ), new Point( 0, 0 ), "MinePlex") ); } catch ( IOException e ) { e.printStackTrace(); }
		
		// Elemente hinzufügen
		
		setLayout( null );
		
		BPlay = new JButton( "Spiel starten" );
		BCredits = new JButton( "Credits" );
		BExit = new JButton( "Beenden" );
		
		BPlay.addActionListener( this );
		BCredits.addActionListener( this );
		BExit.addActionListener( this );
		
		BPlay.setBounds( 20, 20, 150, 30 );
		BCredits.setBounds( 20, 70, 150, 30 );
		BExit.setBounds( 20, 120, 150, 30 );
		
		add( BPlay );
		add( BCredits );
		add( BExit );
		
		setVisible( true );
		
	}
	
	// Methoden
	
	public static void main( String[] args ) {
		
		frame = new MainFrame();
		
	}
	
	public void actionPerformed( ActionEvent e ) {
		
		if ( e.getSource().equals( MainFrame.BPlay ) ) { world = new World(); } else
		
		if ( e.getSource().equals( MainFrame.BCredits ) ) { credits = new Credits(); } else
		
		if ( e.getSource().equals( MainFrame.BExit ) ) { frame.dispose(); }
		
	}
	
}

Die World:
Java:
package net.diegamingbrueder.games.MinePlex;

import java.awt.Graphics;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import javax.imageio.ImageIO;
import javax.swing.JFrame;

public class World extends JFrame implements KeyListener, Runnable, Serializable {
	
	// Deklarationen
	
    private static final long serialVersionUID = 1L;
    
    public static int width = 500, height = 500;
    
    public static Graphics g;
    private static BufferedImage chars, blocks, items;
    
    private static ObjectInputStream input;
    private static ObjectOutputStream output;
    
    private static int[][] world = new int[ 100 ][ 10 ];
    private static Character character;
    private static int[][] Items = new int[ world.length ][ world[ 0 ].length ];
    
    public static final int size = 32;
    public static int sX = 3, sY = 25;
    
    // Konstruktoren
	
	public World() {
		
		// Frame vorbereiten
			
			super( "MinePlex -  Build 1.0.0" );
			setSize( width, height );
			setResizable( false );
			setLocationRelativeTo( null );
			setDefaultCloseOperation( JFrame.HIDE_ON_CLOSE );
			addKeyListener( this );
			setIconImage( Toolkit.getDefaultToolkit().getImage( "res/MinePlex/icon.png" ) );
			
		
		// Texturen einlesen
			
			try { setCursor( Toolkit.getDefaultToolkit().createCustomCursor( ImageIO.read( new File( "res/MinePlex/cursor.png" ) ), new Point( 0, 0 ), "MinePlex") ); } catch ( IOException e ) { e.printStackTrace(); }
			try { chars = ImageIO.read( new File( "res/MinePlex/chars.png" ) ); } catch ( IOException e ) { e.printStackTrace(); }
			try { blocks = ImageIO.read( new File( "res/MinePlex/blocks.png" ) ); } catch ( IOException e ) { e.printStackTrace(); }
			try { items = ImageIO.read( new File( "res/MinePlex/items.png" ) ); } catch ( IOException e ) { e.printStackTrace(); }
		
		g = getGraphics();
		setVisible( true );
		
		load();
		new Thread( this ).start();
		
	}
	
	// Methoden
	
	@ Override
    public void run() {
		
		while ( true ) {
			
			try { Thread.sleep( 50 ); } catch ( InterruptedException e ) { e.printStackTrace(); }
			
			if ( whichBlock( (int) ( character.x + 0.5 * size ), (int) ( character.y + 2.5 * size ) ) == 0 ) {
			
				character.move( 0, (int) ( 0.5 * size ) );
				repaint();
			
			} else {
				
				while ( whichBlock( (int) ( character.x + 0.5 * size ), character.y + 2 * size + 1 ) == 0 ) { character.move( 0, 1 ); }
				repaint();
				
			}
			
		}
		
	}
	
	public static int whichBlock( int x, int y ) { x /= size; y /= size; return world[ x ][ y ]; }
	
	public void paint( Graphics g ) {
		
		for ( int x = 0; x < world.length; x++ ) { for ( int y = 0; y < world[ 0 ].length; y++ ) { g.drawImage( blocks, x * size + sX, y * size + sY, x * size + size + sX, y * size + size + sY, world[ x ][ y ] * size, 0, world[ x ][ y ] * size + size, size, null ); } }
		g.drawImage( chars, character.x + sX, character.y + sY, character.x + size + sX, character.y + 2 * size + sY, character.g * size, 0, character.g * size + size, 2 * size, null );
		for ( int x = 0; x < Items.length; x++ ) { for ( int y = 0; y < Items[ 0 ].length; y++ ) { g.drawImage( items, (int) ( x * size +  0.25 * size + sX ), (int) ( y * size + 0.25 * size + sY ), (int) ( x * size + 0.75 * size + sX ), (int) ( y * size + 0.75 * size + sY ), (int) ( Items[ 0 ][ 0 ] * 0.5 * size ), 0, (int) ( Items[ x ][ y ] * 0.5 * size + 0.5 * size ), (int) ( 0.5 * size ), null ); } }
		
		g.dispose();
		
	}
	
	public static void scroll( int sX, int sY ) { World.sX += sX; World.sY += sY; }
	
	public void load() { // Spielstand laden
				
		if ( new File( "World.MinePlex-World" ).exists() ) {
			
			try {
				
				input = new ObjectInputStream( new BufferedInputStream( new FileInputStream( "World.MinePlex-World" ) ) );
				world = (int[][]) input.readObject();
				input.close();
				
			} catch ( IOException e ) { e.printStackTrace(); } catch ( ClassNotFoundException e ) { e.printStackTrace(); } finally { if ( input != null ) { try { input.close(); } catch ( IOException e ) { e.printStackTrace(); } } }
			
			input = null;
			
		} else {
			
			for ( int x = 0; x < world.length; x++ ) { for ( int y = 0; y < world[ 0 ].length; y++ ) { if ( x == 0 || y == 0 || x == world.length - 1 || y == world[ 0 ].length - 1 ) { world[ x ][ y ] = 1; } } }
			character = new Character( 2 * size, 2 * size );
			
		}
		
		repaint();
		
	}
	
	public void save() { // Spielstand speichern
		
		try {
			
			output = new ObjectOutputStream( new BufferedOutputStream( new FileOutputStream( "World.MinePlex-World" ) ) );
			output.writeObject( world );
			output.close();
			
		} catch ( IOException e ) { e.printStackTrace(); } finally { if ( output != null ) { try { output.close(); } catch ( IOException e ) { e.printStackTrace(); } } }
		
		output = null;
		
	}
	
	@ Override
    public void keyPressed( KeyEvent e ) {
		
	    switch ( e.getKeyCode() ) {
	    	
	    	case KeyEvent.VK_ESCAPE : dispose(); break;
	    	case KeyEvent.VK_S : save(); break;
	    	case KeyEvent.VK_UP : character.move( 0, -size ); repaint(); break;
	    	case KeyEvent.VK_LEFT : character.move( -size, 0 ); repaint(); break;
	    	case KeyEvent.VK_DOWN : character.move( 0, size ); repaint(); break;
	    	case KeyEvent.VK_RIGHT : character.move( size, 0 ); repaint(); break;
	    	
	    }
	    
    }
	
	@ Override
    public void keyReleased( KeyEvent e ) {
		
		switch ( e.getKeyCode() ) {
	    	
			case KeyEvent.VK_ESCAPE : dispose(); break;
			case KeyEvent.VK_S : save(); break;
	    	case KeyEvent.VK_UP : character.move( 0, -size ); repaint(); break;
	    	case KeyEvent.VK_LEFT : character.move( -size, 0 ); repaint(); break;
	    	case KeyEvent.VK_DOWN : character.move( 0, size ); repaint(); break;
	    	case KeyEvent.VK_RIGHT : character.move( size, 0 ); repaint(); break;
			
	    }
	    
    }
	
	@ Override
    public void keyTyped( KeyEvent e ) {
		
		switch ( e.getKeyCode() ) {
	    	
			case KeyEvent.VK_ESCAPE : dispose(); break;
			case KeyEvent.VK_S : save(); break;
	    	case KeyEvent.VK_UP : character.move( 0, -size ); repaint(); break;
	    	case KeyEvent.VK_LEFT : character.move( -size, 0 ); repaint(); break;
	    	case KeyEvent.VK_DOWN : character.move( 0, size ); repaint(); break;
	    	case KeyEvent.VK_RIGHT : character.move( size, 0 ); repaint(); break;
			
	    }
	    
    }
	
}

Der Character:
Java:
package net.diegamingbrueder.games.MinePlex;

public class Character {
	
	// Deklarationen
	
	public int x, y, g = 1;
	
	// Konstruktoren
	
	public Character( int x, int y ) { this.x = x; this.y = y; }
	
	public void move( int dirX, int dirY ) {
		
		if ( World.whichBlock( (int) ( x + 0.5 * World.size + dirX ), (int) ( y + 2.125 * World.size + dirY ) ) == 0 ) { x += dirX; y += dirY; }
		if ( x + World.sX < World.width / 3 ) { World.scroll( ( World.width / 3 ) - ( x + World.sX ), 0 ); }
		if ( x + World.sX > World.width * 2 / 3 ) { World.scroll( ( World.width * 2 / 3 ) - ( x + World.sX ), 0 ); }
		if ( y + World.sY < World.height / 3 ) { World.scroll( 0, ( World.height / 3 ) - ( y + World.sY ) ); }
		if ( y + World.sY > World.height * 2 / 3 ) { World.scroll( 0, ( World.height * 2 / 3 ) - ( y + World.sY ) ); }
		
	}
	
}

Und die Credits:
Java:
package net.diegamingbrueder.games.MinePlex;

import java.awt.Point;
import java.awt.Toolkit;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class Credits extends JFrame {
	
	// Deklarationen
	
    private static final long serialVersionUID = 1L;
    
    private static JLabel ProgrammerL, ProgrammerV, TexturesL, TexturesV;
	
    // Konstruktoren
    
    public Credits() {
    	
    	// Frame vorbereiten
    		
    		super( "Credits" );
    		setSize( 250, 120 );
    		setResizable( false );
    		setLocationRelativeTo( null );
    		setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
    		setIconImage( Toolkit.getDefaultToolkit().getImage( "res/MinePlex/icon.png" ) );
    		try { setCursor( Toolkit.getDefaultToolkit().createCustomCursor( ImageIO.read( new File( "res/MinePlex/cursor.png" ) ), new Point( 0, 0 ), "MinePlex") ); } catch ( IOException e ) { e.printStackTrace(); }
		
    	// Elemente hinzufügen
    		
    		setLayout( null );
    		
    		ProgrammerL = new JLabel( "Programmierer: " );
    		ProgrammerV = new JLabel( "Richtsfeld Robin" );
    		TexturesL = new JLabel( "Texturen: " );
    		TexturesV = new JLabel( "Wagner Jonas" );
    		
    		ProgrammerL.setBounds( 20, 20, 100, 20 );
    		ProgrammerV.setBounds( 130, 20, 100, 20 );
    		TexturesL.setBounds( 55, 50, 100, 20 );
    		TexturesV.setBounds( 130, 50, 100, 20 );
    		
    		add( ProgrammerL );
    		add( ProgrammerV );
    		add( TexturesL );
    		add( TexturesV );
    	
		setVisible( true);
    	
    }
    
}

Danke im Voraus!
 

Anhänge

  • workspace.zip
    32,8 KB · Aufrufe: 3

Highchiller

Bekanntes Mitglied
Also ich habs mir nicht genau angeguckt aber ich hab 2 Dinge die ich dir auf jedenfall mitgeben will.

1. Und das ist ganz wichtig... Sowas macht man nicht:
Java:
for ( int x = 0; x < Items.length; x++ ) { for ( int y = 0; y < Items[ 0 ].length; y++ ) { g.drawImage( items, (int) ( x * size +  0.25 * size + sX ), (int) ( y * size + 0.25 * size + sY ), (int) ( x * size + 0.75 * size + sX ), (int) ( y * size + 0.75 * size + sY ), (int) ( Items[ 0 ][ 0 ] * 0.5 * size ), 0, (int) ( Items[ x ][ y ] * 0.5 * size + 0.5 * size ), (int) ( 0.5 * size ), null ); } }

Das kann niemand lesen... schlimmster code ever :D Das schreibt man so:
Java:
		for ( int x = 0; x < Items.length; x++ ) { 
			for ( int y = 0; y < Items[ 0 ].length; y++ ) { 
				g.drawImage( 
						items, 
						(int) ( x * size + 0.25 * size + sX ), 
						(int) ( y * size + 0.25 * size + sY ), 
						(int) ( x * size + 0.75 * size + sX ), 
						(int) ( y * size + 0.75 * size + sY ), 
						(int) ( Items[ 0 ][ 0 ] * 0.5 * size ), 
						0, 
						(int) ( Items[ x ][ y ] * 0.5 * size + 0.5 * size ), 
						(int) ( 0.5 * size ), 
						null ); 
			}
		}

Und wenn du noch cooler bist, dann schreibst du jetzt in jeder zeile ein kleinen Kommentar welche beträge das da sind. Dann findet man das viel schneller und eventuelle Fehler ebenfalls.

So. Jetzt zum flimmern. Um flimmern zu vermeiden, falls man viel und oft neu zeichnen muss, greift zum sogenannten double buffering. Das Prinzipt ist hier sehr anschaulich erklärt.
Double Buffering in Java

Was das verrücken von der Welt angeht, würde ich dir empfehlen deinen Code besser zu strukturieren (wie oben gezeigt) und dann mal schaust ob alle x-y-Koordinaten überhaupt stimmen.

Klingt nämlich als wenn dort der Fehler liegt.
 

Androbin

Bekanntes Mitglied
@Highchiller
Puh, also beim "Double Buffering" blicke ich irgendwie nicht so ganz durch!
Jedenfalls habe ich deinen Rat zur Übersichtlichkeit befolgt, hier der Quellcode:

Der MainFrame:
package net.diegamingbrueder.games.MinePlex;

import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;

public class MainFrame extends JFrame implements ActionListener {

// Deklarationen

private static final long serialVersionUID = 1L;

public static JFrame frame;
public static Credits credits;
public static JButton BPlay, BCredits, BExit;

public static World world;

// Konstruktoren

public MainFrame() {

// Frame erzeugen

super( "MinePlex" );
setSize( 200, 200 );
setResizable( false );
setLocationRelativeTo( null );
setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
setIconImage( Toolkit.getDefaultToolkit().getImage( "res/MinePlex/icon.png" ) );

try {

setCursor( Toolkit.getDefaultToolkit().createCustomCursor( ImageIO.read( new File( "res/MinePlex/cursor.png" ) ), new Point( 0, 0 ), "MinePlex") );

} catch ( IOException e ) {

e.printStackTrace();

}

// Elemente hinzufügen

setLayout( null );

BPlay = new JButton( "Spiel starten" );
BCredits = new JButton( "Credits" );
BExit = new JButton( "Beenden" );

BPlay.addActionListener( this );
BCredits.addActionListener( this );
BExit.addActionListener( this );

BPlay.setBounds( 20, 20, 150, 30 );
BCredits.setBounds( 20, 70, 150, 30 );
BExit.setBounds( 20, 120, 150, 30 );

add( BPlay );
add( BCredits );
add( BExit );

setVisible( true );

}

// Methoden

public static void main( String[] args ) {

frame = new MainFrame();

}

public void actionPerformed( ActionEvent e ) {

if ( e.getSource().equals( MainFrame.BPlay ) ) {

world = new World();

} else if ( e.getSource().equals( MainFrame.BCredits ) ) {

credits = new Credits();

} else if ( e.getSource().equals( MainFrame.BExit ) ) {

frame.dispose();

}

}

}
Die World:
package net.diegamingbrueder.games.MinePlex;

import java.awt.Graphics;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io_ObjectInputStream;
import java.io_ObjectOutputStream;
import java.io.Serializable;
import javax.imageio.ImageIO;
import javax.swing.JFrame;

public class World extends JFrame implements KeyListener, Runnable, Serializable {

// Deklarationen

private static final long serialVersionUID = 1L;

public static int width = 500, height = 500;

public static Graphics g;
private static BufferedImage chars, blocks, items;

private static ObjectInputStream input;
private static ObjectOutputStream output;

public static int[][] world = new int[ 100 ][ 10 ];
private static Character character;
private static int[][] Items = new int[ world.length ][ world[ 0 ].length ];

public static final int size = 32;
public static int sX = 3, sY = 25;

// Konstruktoren

public World() {

// Frame vorbereiten

super( "MinePlex - Build 1.0.0" );
setSize( width, height );
setResizable( false );
setLocationRelativeTo( null );
setDefaultCloseOperation( JFrame.HIDE_ON_CLOSE );
addKeyListener( this );
setIconImage( Toolkit.getDefaultToolkit().getImage( "res/MinePlex/icon.png" ) );


// Texturen einlesen

try {

setCursor( Toolkit.getDefaultToolkit().createCustomCursor( ImageIO.read( new File( "res/MinePlex/cursor.png" ) ), new Point( 0, 0 ), "MinePlex") );

} catch ( IOException e ) {

e.printStackTrace();

}

try {

chars = ImageIO.read( new File( "res/MinePlex/chars.png" ) );

} catch ( IOException e ) {

e.printStackTrace();

}

try {

blocks = ImageIO.read( new File( "res/MinePlex/blocks.png" ) );

} catch ( IOException e ) {

e.printStackTrace();

}

try {

items = ImageIO.read( new File( "res/MinePlex/items.png" ) );

} catch ( IOException e ) {

e.printStackTrace();

}

g = getGraphics();
setVisible( true );

load();
new Thread( this ).start();

}

// Methoden

@ Override
public void run() { // Schwerkraft, etc.

while ( true ) {

try {

Thread.sleep( 50 );

} catch ( InterruptedException e ) {

e.printStackTrace();

}

if ( world[ (int) ( character.x + 0.5 * size ) / size ][ (int) ( character.y + 2.5 * size ) / size ] == 0 ) {

character.move( 0, (int) ( 0.5 * size ) );
repaint();

} else {

while ( world[ (int) ( character.x + 0.5 * size ) / size ][ ( character.y + 2 * size + 1 ) / size ] == 0 ) {

character.move( 0, 1 );

}

repaint();

}

}

}

public void paint( Graphics g ) {

for ( int x = 0; x < world.length; x++ ) {

for ( int y = 0; y < world[ 0 ].length; y++ ) {

g.drawImage( blocks, x * size + sX, y * size + sY, x * size + size + sX, y * size + size + sY, world[ x ][ y ] * size, 0, world[ x ][ y ] * size + size, size, null );

}

}

g.drawImage( chars, character.x + sX, character.y + sY, character.x + size + sX, character.y + 2 * size + sY, character.g * size, 0, character.g * size + size, 2 * size, null );

for ( int x = 0; x < Items.length; x++ ) {

for ( int y = 0; y < Items[ 0 ].length; y++ ) {

g.drawImage( items, (int) ( x * size + 0.25 * size + sX ), (int) ( y * size + 0.25 * size + sY ), (int) ( x * size + 0.75 * size + sX ), (int) ( y * size + 0.75 * size + sY ), (int) ( Items[ 0 ][ 0 ] * 0.5 * size ), 0, (int) ( Items[ x ][ y ] * 0.5 * size + 0.5 * size ), (int) ( 0.5 * size ), null );

}

}

g.dispose();

}

public void load() { // Spielstand laden

if ( new File( "World.MinePlex-World" ).exists() ) {

for ( int x = 0; x < world.length; x++ ) {

for ( int y = 0; y < world[ 0 ].length; y++ ) {

if ( world[ x ][ y ] == -1 ) {

character = new Character( x, y );
world[ x ][ y ] = 0;

}

}

}

try {

input = new ObjectInputStream( new BufferedInputStream( new FileInputStream( "World.MinePlex-World" ) ) );
world = (int[][]) input.readObject();
input.close();

} catch ( IOException e ) { e.printStackTrace(); } catch ( ClassNotFoundException e ) { e.printStackTrace(); } finally { if ( input != null ) { try { input.close(); } catch ( IOException e ) { e.printStackTrace(); } } }

input = null;

} else {

for ( int x = 0; x < world.length; x++ ) {

for ( int y = 0; y < world[ 0 ].length; y++ ) {

if ( x == 0 || y == 0 || x == world.length - 1 || y == world[ 0 ].length - 1 ) {

world[ x ][ y ] = 1;

}

}

}

character = new Character( 2 * size, 2 * size );

}

repaint();

}

public void save() { // Spielstand speichern

world[ character.x ][ character.y ] = -1;

try {

output = new ObjectOutputStream( new BufferedOutputStream( new FileOutputStream( "World.MinePlex-World" ) ) );
output.writeObject( world );
output.close();

} catch ( IOException e ) {

e.printStackTrace();

} finally {

if ( output != null ) {

try {

output.close();

} catch ( IOException e ) {

e.printStackTrace();

}

}

}

world[ character.x ][ character.y ] = 0;

output = null;

}

@ Override
public void keyPressed( KeyEvent e ) {

switch ( e.getKeyCode() ) {

case KeyEvent.VK_ESCAPE :

dispose();
break;

case KeyEvent.VK_S :
save();
break;

case KeyEvent.VK_UP :

character.move( 0, -size );
repaint();
break;

case KeyEvent.VK_LEFT :

character.move( -size, 0 );
repaint();
break;

case KeyEvent.VK_DOWN :

character.move( 0, size );
repaint();
break;

case KeyEvent.VK_RIGHT :

character.move( size, 0 );
repaint();
break;

}

}

@ Override
public void keyReleased( KeyEvent e ) {

switch ( e.getKeyCode() ) {

case KeyEvent.VK_ESCAPE :

dispose();
break;

case KeyEvent.VK_S :
save();
break;

case KeyEvent.VK_UP :

character.move( 0, -size );
repaint();
break;

case KeyEvent.VK_LEFT :

character.move( -size, 0 );
repaint();
break;

case KeyEvent.VK_DOWN :

character.move( 0, size );
repaint();
break;

case KeyEvent.VK_RIGHT :

character.move( size, 0 );
repaint();
break;

}

}

@ Override
public void keyTyped( KeyEvent e ) {

switch ( e.getKeyCode() ) {

case KeyEvent.VK_ESCAPE :

dispose();
break;

case KeyEvent.VK_S :
save();
break;

case KeyEvent.VK_UP :

character.move( 0, -size );
repaint();
break;

case KeyEvent.VK_LEFT :

character.move( -size, 0 );
repaint();
break;

case KeyEvent.VK_DOWN :

character.move( 0, size );
repaint();
break;

case KeyEvent.VK_RIGHT :

character.move( size, 0 );
repaint();
break;

}

}

}
Der Character:
package net.diegamingbrueder.games.MinePlex;

public class Character {

// Deklarationen

public int x, y, g = 1;

// Konstruktoren

public Character( int x, int y ) {

this.x = x;
this.y = y;

}

public void move( int dirX, int dirY ) {

if ( World.world[ (int) ( x + 0.5 * World.size + dirX ) / World.size ][ (int) ( y + 2.125 * World.size + dirY ) / World.size ] == 0 ) {

x += dirX;
y += dirY;

}

if ( x + World.sX < World.width / 3 ) {

World.sX += ( ( World.width / 3 ) - ( x + World.sX ) );

}

if ( x + World.sX > World.width * 2 / 3 ) {

World.sX += ( ( World.width * 2 / 3 ) - ( x + World.sX ) );

}

if ( y + World.sY < World.height / 3 ) {

World.sY += ( ( World.height / 3 ) - ( y + World.sY ) );

}

if ( y + World.sY > World.height * 2 / 3 ) {

World.sY += ( ( World.height * 2 / 3 ) - ( y + World.sY ) );

}

}

}
Die Credits:
package net.diegamingbrueder.games.MinePlex;

import java.awt.Point;
import java.awt.Toolkit;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class Credits extends JFrame {

// Deklarationen

private static final long serialVersionUID = 1L;

private static JLabel ProgrammerL, ProgrammerV, TexturesL, TexturesV;

// Konstruktoren

public Credits() {

// Frame vorbereiten

super( "Credits" );
setSize( 250, 120 );
setResizable( false );
setLocationRelativeTo( null );
setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
setIconImage( Toolkit.getDefaultToolkit().getImage( "res/MinePlex/icon.png" ) );
try {

setCursor( Toolkit.getDefaultToolkit().createCustomCursor( ImageIO.read( new File( "res/MinePlex/cursor.png" ) ), new Point( 0, 0 ), "MinePlex") );

} catch ( IOException e ) {

e.printStackTrace();

}

// Elemente hinzufügen

setLayout( null );

ProgrammerL = new JLabel( "Programmierer: " );
ProgrammerV = new JLabel( "Richtsfeld Robin" );
TexturesL = new JLabel( "Texturen: " );
TexturesV = new JLabel( "Wagner Jonas" );

ProgrammerL.setBounds( 20, 20, 100, 20 );
ProgrammerV.setBounds( 130, 20, 100, 20 );
TexturesL.setBounds( 55, 50, 100, 20 );
TexturesV.setBounds( 130, 50, 100, 20 );

add( ProgrammerL );
add( ProgrammerV );
add( TexturesL );
add( TexturesV );

setVisible( true);

}

}
Im Anhang auch diesmal wieder der workspace!
 

Anhänge

  • workspace.zip
    33,4 KB · Aufrufe: 1

Highchiller

Bekanntes Mitglied
Also es schaut schon besser aus :D Aber da geht noch was.

Aber egal. Das Double-Buffering ist doch ganz gut erklärt worden. Was verstehst du denn daran nicht?

Ich hab das schnell eingebaut und es scheint zu funktionieren. Gleichzeitig ist damit das Problem mit deinem "versetzten Neuzeichnen" auch behoben worden.

Also genau wie in dem Link, benennst du deine paint(Graphics g) Methode mal um in "bigPaint(Graphics g)". Dann erstellst du dir 2 neue Elemente, einmal die gfxConf und das offImg (wie im link). Und dann schreibst du eine neue, eigene paint(Graphics g) Methode die so aussieht:
Java:
	@Override
	public void paint( Graphics g ){
		if ( offImg == null ){
			offImg = gfxConf.createCompatibleImage(width, height);
			bigPaint( offImg.createGraphics() );
		}
		
		g.drawImage(offImg, 0, 0, this);
	}

So. Wenn du das jetzt ausführst, wird das zwar schön gezeichnet, aber es wird nicht geupdated. Wieso nicht? Naja weil wir nur updaten wenn offImg == null gilt. Das gilt nur beim allerersten aufruf. Macht also kein Sinn so.

Eine etwas unelegante Lösung wäre jetzt, noch fix eine eigene repaint Methode zu schreiben:
Java:
	private void repaint(boolean bool){
		if ( bool ) offImg = null;
		repaint();
	}

Und jedes mal wo DU selbst repaint aufrufst, übergibst du jetzt noch true.

Und schon fertig... schaut ungefähr so aus wies soll und es flimmert nicht mehr.

Begründung. Die Methode paint() wird extrem oft augerufen und zwar von der Graka. Die will ja immer schön das Bild haben was auf den Bildschirm soll.
Jetzt gibt die Methode aber immer nur das Bild wieder zurück, was sowieso schon gezeichnet wurde. Also muss sie nicht lange rechnen sondern sagt, ach guck ma,ich hab sowieso noch nix neues für dich. Nimm mal das alte bild.

Wenn du jetzt repaint(true) aufrust, weiß die paint Methode, da hat sich was geändert (denn offImg == null). Also updaten wir das schnell und gebens an die Graka weiter. => Flimmern weg.

Aber ein anderes Problem wird nun deutlicher denn je. Du zeichnest mit falschen koordinaten. Denn anscheinend geht dein Spielfeld über das Fenster hinaus. Das sollte ja eigentlich nicht sein. Daran musst du jetzt weiter tüfteln.
 

Androbin

Bekanntes Mitglied
@Highchiller
Also das mit dem versetzten Zeichnen hätte ich bereits gelöst mit: :applaus:
Java:
 g.clearRect( 0, 0, width, height );

Jedenfalls hat "Double Buffering" gegen das Flackern geholfen! :toll:

Allerdings habe ich dann immer noch ein paar Probleme:
1. Kann man theoretisch unendlich hoch "fliegen" statt kurz hüpfen,
2. Kann man mit seiner "oberen Hälfte" in die Decke, und, und, und, ... ! :popcorn:
 
Zuletzt bearbeitet:

JCODA

Top Contributor
Wow.

Seit dem Betreiberwechsel hat die Qualität echt abgenommen hier im JFO!

LEUTE!

hier wird
Code:
g = getGraphics();

verwendet!

es wird die paint(Graphics g) von einem JFrame! überschrieben (und das ohne! super.paint(g) Aufruf!)

und ihr ratet ihm ehrlich zu Doublebuffering?! (das nebenbei in Swing AUTOMATISCH verhanden ist, wenn man Swing richtig benutzen würde...)

Tipp:

- überschreibe nicht die paint von einem Container, sondern nimm ein JPanel und überschreibe dort die paintComponent(..)
- benutze niemals getGraphics() auf einer Component!
- rufe jedesmal zuallererst die super-methode in einer paint()/paintComponent() auf.
- rufe nicht g.dispose(); in der von JFrame/JPanel paint/paintcomponent-Methoden auf.
 

Androbin

Bekanntes Mitglied
Hilfe: Auf einmal zeichnet er gar nichts mehr! :shock: ;(
Gestern hat das Double Buffering wirklich toll funktioniert, aber jetzt geht da gar nichts mehr !!!

Hier der Code:

MainFrame:
Java:
package net.diegamingbrueder.games.MinePlex;

import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;

public class MainFrame extends JFrame implements ActionListener {
	
	// Deklarationen
	
    private static final long serialVersionUID = 1L;
    
	public static JFrame frame;
	public static Credits credits;
	public static JButton BPlay, BCredits, BExit;
	
	public static World world;
	
	// Konstruktoren
	
    public MainFrame() {
		
		// Frame erzeugen
		
		super( "MinePlex" );
		setSize( 200, 200 );
		setResizable( false );
		setLocationRelativeTo( null );
		setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
		setIconImage( Toolkit.getDefaultToolkit().getImage( "res/MinePlex/icon.png" ) );
		
		try {
			
			setCursor( Toolkit.getDefaultToolkit().createCustomCursor( ImageIO.read( new File( "res/MinePlex/cursor.png" ) ), new Point( 0, 0 ), "MinePlex") );
			
		} catch ( IOException e ) {
			
			e.printStackTrace();
			
		}
		
		// Elemente hinzufügen
		
		setLayout( null );
		
		BPlay = new JButton( "Spiel starten" );
		BCredits = new JButton( "Credits" );
		BExit = new JButton( "Beenden" );
		
		BPlay.addActionListener( this );
		BCredits.addActionListener( this );
		BExit.addActionListener( this );
		
		BPlay.setBounds( 20, 20, 150, 30 );
		BCredits.setBounds( 20, 70, 150, 30 );
		BExit.setBounds( 20, 120, 150, 30 );
		
		add( BPlay );
		add( BCredits );
		add( BExit );
		
		setVisible( true );
		
	}
	
	// Methoden
	
	public static void main( String[] args ) {
		
		frame = new MainFrame();
		
	}
	
	public void actionPerformed( ActionEvent e ) {
		
		if ( e.getSource().equals( MainFrame.BPlay ) ) {
			
			world = new World();
			
		} else if ( e.getSource().equals( MainFrame.BCredits ) ) {
			
			credits = new Credits();
			
		} else if ( e.getSource().equals( MainFrame.BExit ) ) {
			
			frame.dispose();
			
		}
		
	}
	
}

World:
Java:
package net.diegamingbrueder.games.MinePlex;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import javax.imageio.ImageIO;
import javax.swing.JFrame;

public class World extends JFrame implements KeyListener, Runnable, Serializable {
	
	// Deklarationen
	
    private static final long serialVersionUID = 1L;
    
    public static int width = 500, height = 500;
    private boolean isRunning = false;
    
    public static Graphics g;
    private static BufferedImage chars, blocks, items;
    
    private final GraphicsConfiguration gfxConf = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
    private BufferedImage offImg;
    
    private static ObjectInputStream input;
    private static ObjectOutputStream output;
    
    public static int[][] world = new int[ 256 ][ 64 ];
    private static Character character;
    private static int[][] Items = new int[ world.length ][ world[ 0 ].length ];
    
    public static final int size = 32;
    public static int sX = 3, sY = 25;
    
    // Konstruktoren
	
	public World() {
		
		// Frame vorbereiten
			
			super( "MinePlex -  Build 1.0.0" );
			setSize( width, height );
			setResizable( false );
			setLocationRelativeTo( null );
			setDefaultCloseOperation( JFrame.HIDE_ON_CLOSE );
			addKeyListener( this );
			setIconImage( Toolkit.getDefaultToolkit().getImage( "res/MinePlex/icon.png" ) );
			setBackground( Color.BLACK );
			
		
		// Texturen einlesen
			
			try {
				
				setCursor( Toolkit.getDefaultToolkit().createCustomCursor( ImageIO.read( new File( "res/MinePlex/cursor.png" ) ), new Point( 0, 0 ), "MinePlex") );
				
			} catch ( IOException e ) {
				
				e.printStackTrace();
				
			}
			
			try {
				
				chars = ImageIO.read( new File( "res/MinePlex/chars.png" ) );
				
			} catch ( IOException e ) {
				
				e.printStackTrace();
				
			}
			
			try {
				
				blocks = ImageIO.read( new File( "res/MinePlex/blocks.png" ) );
				
			} catch ( IOException e ) {
				
				e.printStackTrace();
				
			}
			
			try {
				
				items = ImageIO.read( new File( "res/MinePlex/items.png" ) );
				
			} catch ( IOException e ) {
				
				e.printStackTrace();
				
			}
		
		g = getGraphics();
		setVisible( true );
		
		load();
		isRunning = true;
		new Thread( this ).start();
		
	}
	
	// Methoden
	
	@ Override
    public void run() { // Schwerkraft, etc.
		
		while ( isRunning ) {
			
			try {
				
				Thread.sleep( 5 );
				
			} catch ( InterruptedException e ) {
				
				e.printStackTrace();
				
			}
			
			if ( world[ (int) ( character.x + 0.5 * size ) / size ][ (int) ( character.y + 2.5 * size ) / size ] == 0 ) {
			
				character.move( 0, (int) ( 0.125 * size ) );
				repaint( true );
			
			} else {
				
				while ( world[ (int) ( character.x + 0.5 * size ) / size ][ ( character.y + 2 * size + 1 ) / size ] == 0 ) {
					
					character.move( 0, 1 );
					
				}
				
				repaint( true );
				
			}
			
		}
		
	}
	
	@Override
    public void paint( Graphics g ){
		
        if ( offImg == null ) {
        	
            offImg = gfxConf.createCompatibleImage(width, height);
            bigPaint( offImg.createGraphics() );
            
        }
        
        g.drawImage( offImg, 0, 0, this );
    }
	
	public void bigPaint( Graphics g ) {
		
		for ( int x = 0; x < world.length; x++ ) {
			
			for ( int y = 0; y < world[ 0 ].length; y++ ) {
				
				g.drawImage( blocks, x * size + sX, y * size + sY, x * size + size + sX, y * size + size + sY, world[ x ][ y ] * size, 0, world[ x ][ y ] * size + size, size, null );
				
			}
			
		}
		
		g.drawImage( chars, character.x + sX, character.y + sY, character.x + size + sX, character.y + 2 * size + sY, character.g * size, 0, character.g * size + size, 2 * size, null );
		
		for ( int x = 0; x < Items.length; x++ ) {
			
			for ( int y = 0; y < Items[ 0 ].length; y++ ) {
				
				g.drawImage( items, (int) ( x * size +  0.25 * size + sX ), (int) ( y * size + 0.25 * size + sY ), (int) ( x * size + 0.75 * size + sX ), (int) ( y * size + 0.75 * size + sY ), (int) ( Items[ 0 ][ 0 ] * 0.5 * size ), 0, (int) ( Items[ x ][ y ] * 0.5 * size + 0.5 * size ), (int) ( 0.5 * size ), null );
				
			}
			
		}
		
		g.dispose();
		
	}
	
	private void repaint( boolean bool ) {
		
        if ( bool ) {
        	
        	offImg = null;
        	
        }
        
        repaint();
        
    }
	
	public void load() { // Spielstand laden
		
		if ( new File( "World.MinePlex-World" ).exists() ) {
			
			try {
				
				input = new ObjectInputStream( new BufferedInputStream( new FileInputStream( "World.MinePlex-World" ) ) );
				world = (int[][]) input.readObject();
				input.close();
				
			} catch ( IOException e ) { e.printStackTrace(); } catch ( ClassNotFoundException e ) { e.printStackTrace(); } finally { if ( input != null ) { try { input.close(); } catch ( IOException e ) { e.printStackTrace(); } } }
			
			input = null;
			
		} else {
			
			for ( int x = 0; x < world.length; x++ ) {
				
				for ( int y = 0; y < world[ 0 ].length; y++ ) {
					
					if ( x == 0 || y == 0 || x == world.length - 1 || y == world[ 0 ].length - 1 ) {
						
						world[ x ][ y ] = 1;
						
					}
					
				}
				
			}
			
			character = new Character( 2 * size, 2 * size );
			
		}
		
		repaint( true );
		
	}
	
	public void save() { // Spielstand speichern
		
		try {
			
			output = new ObjectOutputStream( new BufferedOutputStream( new FileOutputStream( "World.MinePlex-World" ) ) );
			output.writeObject( world );
			output.close();
			
		} catch ( IOException e ) {
			
			e.printStackTrace();
			
		} finally {
			
			if ( output != null ) {
				
				try {
					
					output.close();
				
				} catch ( IOException e ) {
					
					e.printStackTrace();
					
				}
				
			}
			
		}
		
		output = null;
		
	}
	
	@ Override
    public void keyPressed( KeyEvent e ) {
		
	    switch ( e.getKeyCode() ) {
	    	
	    	case KeyEvent.VK_ESCAPE :
	    		
	    		dispose();
	    		break;
	    		
	    	case KeyEvent.VK_S :
	    		
	    		save();
	    		break;
	    		
	    	case KeyEvent.VK_UP :
	    		
	    		character.move( 0, -size );
	    		repaint( true );
	    		break;
	    		
	    	case KeyEvent.VK_LEFT :
	    		
	    		character.move( -size, 0 );
	    		repaint( true );
	    		break;
	    		
	    	case KeyEvent.VK_DOWN :
	    		
	    		character.move( 0, size );
	    		repaint( true );
	    		break;
	    		
	    	case KeyEvent.VK_RIGHT :
	    		
	    		character.move( size, 0 );
	    		repaint( true );
	    		break;
	    	
	    }
	    
    }
	
	@ Override
    public void keyReleased( KeyEvent e ) {
		
		switch ( e.getKeyCode() ) {
	    	
	    	case KeyEvent.VK_ESCAPE :
	    		
	    		dispose();
	    		break;
	    		
	    	case KeyEvent.VK_S :
	    		
	    		save();
	    		break;
	    		
	    	case KeyEvent.VK_UP :
	    		
	    		character.move( 0, -size );
	    		repaint( true );
	    		break;
	    		
	    	case KeyEvent.VK_LEFT :
	    		
	    		character.move( -size, 0 );
	    		repaint( true );
	    		break;
	    		
	    	case KeyEvent.VK_DOWN :
	    		
	    		character.move( 0, size );
	    		repaint( true );
	    		break;
	    		
	    	case KeyEvent.VK_RIGHT :
	    		
	    		character.move( size, 0 );
	    		repaint( true );
	    		break;
	    	
	    }
	    
    }
	
	@ Override
    public void keyTyped( KeyEvent e ) {
		
		switch ( e.getKeyCode() ) {
	    	
	    	case KeyEvent.VK_ESCAPE :
	    		
	    		dispose();
	    		break;
	    		
	    	case KeyEvent.VK_S :
	    		
	    		save();
	    		break;
	    		
	    	case KeyEvent.VK_UP :
	    		
	    		character.move( 0, -size );
	    		repaint( true );
	    		break;
	    		
	    	case KeyEvent.VK_LEFT :
	    		
	    		character.move( -size, 0 );
	    		repaint( true );
	    		break;
	    		
	    	case KeyEvent.VK_DOWN :
	    		
	    		character.move( 0, size );
	    		repaint( true );
	    		break;
	    		
	    	case KeyEvent.VK_RIGHT :
	    		
	    		character.move( size, 0 );
	    		repaint( true );
	    		break;
	    	
	    }
	    
    }
	
}

Character:
Java:
package net.diegamingbrueder.games.MinePlex;

public class Character {
	
	// Deklarationen
	
	public int x, y, g = 1;
	
	// Konstruktoren
	
	public Character( int x, int y ) {
		
		this.x = x;
		this.y = y;
		
	}
	
	public void move( int dirX, int dirY ) {
		
		if ( World.world[ (int) ( x + 0.5 * World.size + dirX ) / World.size ][ (int) ( y + 2 * World.size + dirY ) / World.size ] == 0 ) {
			
			x += dirX;
			y += dirY;
			
		}
		
		if ( x + World.sX < World.width / 3 ) {
			
			World.sX += ( ( World.width / 3 ) - ( x + World.sX ) );
			
		}
		
		if ( x + World.sX > World.width * 2 / 3 ) {
			
			World.sX += ( ( World.width * 2 / 3 ) - ( x + World.sX ) );
			
		}
		
		if ( y + World.sY < World.height / 3 ) {
			
			World.sY += ( ( World.height / 3 ) - ( y + World.sY ) );
			
		}
		
		if ( y + World.sY > World.height * 2 / 3 ) {
			
			World.sY += ( ( World.height * 2 / 3 ) - ( y + World.sY ) );
			
		}
		
	}
	
}

Credits:
Java:
package net.diegamingbrueder.games.MinePlex;

import java.awt.Point;
import java.awt.Toolkit;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class Credits extends JFrame {
	
	// Deklarationen
	
    private static final long serialVersionUID = 1L;
    
    private static JLabel ProgrammerL, ProgrammerV, TexturesL, TexturesV;
	
    // Konstruktoren
    
    public Credits() {
    	
    	// Frame vorbereiten
    		
    		super( "Credits" );
    		setSize( 250, 120 );
    		setResizable( false );
    		setLocationRelativeTo( null );
    		setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
    		setIconImage( Toolkit.getDefaultToolkit().getImage( "res/MinePlex/icon.png" ) );
    		try {
    			
    			setCursor( Toolkit.getDefaultToolkit().createCustomCursor( ImageIO.read( new File( "res/MinePlex/cursor.png" ) ), new Point( 0, 0 ), "MinePlex") );
    			
    		} catch ( IOException e ) {
    			
    			e.printStackTrace();
    			
    		}
		
    	// Elemente hinzufügen
    		
    		setLayout( null );
    		
    		ProgrammerL = new JLabel( "Programmierer: " );
    		ProgrammerV = new JLabel( "Richtsfeld Robin" );
    		TexturesL = new JLabel( "Texturen: " );
    		TexturesV = new JLabel( "Wagner Jonas" );
    		
    		ProgrammerL.setBounds( 20, 20, 100, 20 );
    		ProgrammerV.setBounds( 130, 20, 100, 20 );
    		TexturesL.setBounds( 55, 50, 100, 20 );
    		TexturesV.setBounds( 130, 50, 100, 20 );
    		
    		add( ProgrammerL );
    		add( ProgrammerV );
    		add( TexturesL );
    		add( TexturesV );
    	
		setVisible( true);
    	
    }
    
}

Im Anhang der Workspace:
 

Anhänge

  • workspace.zip
    37,5 KB · Aufrufe: 1

Androbin

Bekanntes Mitglied
Geht wieder! :toll: Hab die FPS berechnet und in Thread.sleep() eingesetzt!
Allerdings ruckelt es jetzt ziemlich! :bahnhof: ... !!!
 

Androbin

Bekanntes Mitglied
Jetzt passt soweit alles! :toll:
Sollte noch irgendjemand was zu sagen haben, soll er das tun!
Ich werde wohl am Besten diese Thema als erledigt markieren und wenn es wäre noch ein anderes erstellen!

Für die, die es wollen ist im Anhang noch das (vorerst) fertige Eclipse-Projekt:
 

Anhänge

  • workspace.zip
    37,6 KB · Aufrufe: 2

Neue Themen


Oben