# Animation in eigenen Thread auslagern.....



## kaoZ (25. Sep 2014)

Aloha, 

ich steh grad aufm Schlauch, ich habe folgende Klasse erstellt welche eine Animation darstellt,


```
public class Animation implements Drawable{

	private int x;
	private int y;
	private int currentTile;
	private int tileSize;
	private int lastTile;
	
	private String name;
	
	private boolean started;
	
	private BufferedImage tileSet;
	private BufferedImage[] tiles;
	
	public Animation(String name, String source, int tileSize){
		this.name = name;
		this.tileSize = tileSize;
		loadImage(source);
		createTiles();
	}
	
	public Animation(String name, BufferedImage tileSet, int tileSize){
		this.name = name;
		this.tileSet = tileSet;
		this.tileSize = tileSize;
		createTiles();
	}
	
	public Animation(String name, BufferedImage tileSet, int x, int y, int tileSize){
		this.name = name;
		this.tileSet = tileSet;
		this.tileSize = tileSize;
		createTiles(x, y);
	}
	
	private void loadImage(String source){
		try {
			tileSet = ImageIO.read(getClass().getResourceAsStream(source));
		}
		catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private void createTiles(){
		tiles = new BufferedImage[tileSet.getWidth() / tileSize];
		for (int i = 0; i < tiles.length; i++) {
			tiles[i] = tileSet.getSubimage(i * tileSize, 0, tileSize, tileSize);
		}
	}
	
	private void createTiles(int x, int y){
		tiles = new BufferedImage[tileSet.getWidth() / tileSize];
		for (int i = 0; i < tiles.length; i++) {
			tiles[i] = tileSet.getSubimage(x, y, tileSize, tileSize);
		}
	}
	
	public void setFirstTile(int tile){
		if(tile < 0 || tile > tiles.length) {
			throw new ArrayIndexOutOfBoundsException(tile);
		}
		else{
			currentTile = tile;
		}
	}
	
	public void setLastTile(int tile){
		if(tile < currentTile || tile < 0) {
			throw new IllegalArgumentException("tile have to be > as" + currentTile);
		}
		else{
			lastTile = tile;
		}
	}
	
	public void start(){
		this.started = true;
	}
	
	public void stop(){
		this.started = false;
	}
	
	public void setPosition(int x, int y){
		this.x = x;
		this.y = y;
	}
	
	public void setStatic(int tile){
		setFirstTile(tile);
		setLastTile(tile);
	}
	
	@Override
	public void update(){
		if(started) {
			currentTile++;
			if(lastTile == 0) {
				if(currentTile == tiles.length) {
					currentTile = 0;
				}
			}
			else{
				if(currentTile == lastTile) {
					currentTile = 0;
				}
			}
		}
	}

	@Override
	public void draw(Graphics g){
		for (int i = 0; i < tiles.length; i++) {
			g.drawImage(tiles[currentTile], x, y, null);
		}
	}
	
	public int getX()				{return x;}
	public int getY()				{return y;}
	public int getTileSize()		{return tileSize;}
	public String getName()			{return name;}
	public boolean isStarted()		{return started;}

}
```

funktioniert auch reibungslos, allerdings nur wenn ich diese direkt in einem loop zeichnen lasse, füge ich z.B einem Spieler eine Animation hinzu, und lasse diese dann in der Klasse player zeichnen, dessen instanz wiederum im gameloop gezeichnet wird, wird zwar das image gezeichnet nicht aber die abfolge der bilder, sprich ich muss dazu übergehen die Animation in einen eigenen Thread auszulagern, welche solange das started flag gesetzt ist, eben zeichnet, was sie zeichnen soll,

wie würdet ihr da vorgehen ? Timer + TimerTask? ( für ein ggf. später hinzugefügtes delay) oder einen einfachen Thread mit loop ?

wie verhält sich das ganze dann in Verbindung mit dem EDT ? der ja letzendlich zeichnet, muss ich die Threads dann per join zusammenführen ?

über jeden hinweis bin ich dankbar 

EDIT:
Mich verwundet gerade das immer nur das erste bild gezeichnet wird, auch wenn ich ein anderes image aus dem BufferedImge array als startimage setze..... sobald ich in einer konkreten klasse eine animation hinzufüge....vielleicht übersehe ich auch gerade auch einfach was....

die konkreten klassen sind btw. die einzigen die eine Implementierung für das Drawable interface bieten...

übersehe ich ggf. gerade nur ein polymorphie problem ?!


```
public class Mage extends Player{

	Animation walk;
	
	public Mage(String name){
		super(name);
		setTileSet("/images/playable/mage.png");
		init();
	}
	
	@Override
	protected void init(){
		walk = new Animation("walk", getTileSet(), 0, 0, 64);
		walk.setFirstTile(4);
		walk.start();
	}
	
	@Override
	public void update(){
		walk.setPosition(getX(), getY());
		walk.update();
	}

	@Override
	public void draw(Graphics g){
		walk.draw(g);
	}

}
```

hier noch die stelle an der dann gerendert wird :


```
Player player;

...
	
      	
	private void init(){
		image = new BufferedImage(WIDTH * SCALE, HEIGHT * SCALE, BufferedImage.TYPE_INT_RGB);
		running = true;
		player = new Mage("Merlin");
		player.setPosition(50, 50);
	}
	

	private void update(){
		player.update();
	}
	
	private void render(){
		Graphics2D g = (Graphics2D)image.getGraphics();

		clearScreen(g);

		player.draw(g);
		
		g.dispose();
	}
```
*
EDIT:
ich habs , anscheinend liegt es am überladenen konstruktor , dieser initialisiert anschienend doch nicht korrekt insofern ich ein bufferedimage und x und y koordinaten übergebe.... ich meld mich wenn ich eine lösung habe.*

ich habs ..... ich brain.....NOT

Verkackt würde ich sagen ^^


```
private void createTiles(int x, int y){
		tiles = new BufferedImage[tileSet.getWidth() / tileSize];
		for (int i = 0; i < tiles.length; i++) {
			tiles[i] = tileSet.getSubimage(x, y, tileSize, tileSize);  // <<-- x und y gehören da nicht hin.....
		}
	}
```

Lösung falls es wen interessiert ist (noch unoptimiert):


```
private void createTiles(int x, int y){
		BufferedImage subImage = tileSet.getSubimage(x, y, tileSet.getWidth(), tileSet.getHeight());
		tiles = new BufferedImage[subImage.getWidth() / tileSize];
		for (int i = 0; i < tiles.length; i++) {
			tiles[i] = subImage.getSubimage(i * tileSize, 0, tileSize, tileSize);
		}
	}
```


----------



## Androbin (5. Okt 2014)

Hallo kaoZ,

ich weiß, es ist ziemlich mühselig, aber:

Versuche doch mal, so zu tun, als wärst du der Java-Interpreter
und gehe dein Programm Schritt für Schritt durch ...
(Du kannst dir auch die Werte der Variablen notieren)

Ich weiß, das klingt jetzt vielleicht etwas bescheuert,
aber wenn man(n) einfach nicht mehr weiterkommt,
ist das manchmal der letzte Ausweg ...

Frohes Schaffen, Androbin


----------

