# Android OpenGL Bewegen



## Titanpharao (25. Jan 2012)

Halli Hallo,

ich sitze jetzt seit 3 Tagen an der vielleicht "einfachsten" Sache der Welt fest, komme aber wirklich nicht weiter 

Und zwar soll es mal ein Tower Defense Spiel für da Android werden mit OpenGL ES.

Hier ist meine Klasse "Creep" also der Gegner, der sich durch die Tower bewegen soll.


```
package de.liquidtitan.simpletowerdefense.objects;

import android.util.FloatMath;
import android.util.Log;
import de.liquidtitan.simpletowerdefense.game.astar.AStarPathFinder;
import de.liquidtitan.simpletowerdefense.game.astar.Path;
import de.liquidtitan.simpletowerdefense.game.astar.Path.Step;
import de.liquidtitan.simpletowerdefense.game.opengl.basics.GameObject;
import de.liquidtitan.simpletowerdefense.game.opengl.math.Vector2D;
import de.liquidtitan.simpletowerdefense.game.world.World;

public class Creep extends GameObject{

	private final AStarPathFinder finder;
	public final Vector2D velocity=new Vector2D();
	public static final float CREEP_VELOCITY=100f;

	public static final int FINAL_ABS_POSITION_X=8;
	public static final int FINAL_ABS_POSITION_Y=2;

	public Path path=null;

	private int tileX=0;
	private int tileTmpX=0;
	private volatile int tileY=0;
	private volatile int tileTmpY=0;

	public Creep(float x,float y,float width,float height,AStarPathFinder finder){
		super(x,y,width,height);
		this.finder=finder;
	}

	public void setAbsolutePosition(int x,int y){
		tileX=tileTmpX=x;
		tileY=tileTmpY=y;
		path=finder.findPath(tileX,tileY,FINAL_ABS_POSITION_X,FINAL_ABS_POSITION_Y);
		fromPathToVelocity(tileX,tileY);
	}

	public void update(float deltaTime){
		tileX=(int)FloatMath.floor(position.x/World.FIELD_SIZE_X);
		tileY=(int)FloatMath.floor(position.y/World.FIELD_SIZE_Y);
		if(tileX!=tileTmpX||tileY!=tileTmpY){
			tileTmpX=tileX;
			tileTmpY=tileY;
			int x=path.getStep(1).getX();
			int y=path.getStep(1).getY();
			path=finder.findPath(x,y,FINAL_ABS_POSITION_X,FINAL_ABS_POSITION_Y);
			fromPathToVelocity(x,y);
		}
		position.add(velocity.x*deltaTime,velocity.y*deltaTime);
		if(position.x<0)
			position.x=0;
		if(position.y<0)
			position.y=0;
	}

	public void fromPathToVelocity(int absX,int absY){
		if(path!=null){
			Step step=path.getStep(1);
			int stepX=step.getX();
			int stepY=step.getY();
			if(stepX>absX&&stepY==absY){
				velocity.set(CREEP_VELOCITY,0);
			}else if(stepX==absX&&stepY<absY){
				velocity.set(0,-CREEP_VELOCITY);
			}else if(stepX<absX&&stepY==absY){
				velocity.set(-CREEP_VELOCITY,0);
			}else if(stepX==absX&&stepY>absY){
				velocity.set(0,CREEP_VELOCITY);
			}
		}else
			velocity.set(0,0);
	}
}
```

Es wird eine Position übergeben und anhand dieser das Feld berechnet, wo sich die Figur befindet. Der Wegfindealgorithmus übernimmt Start und End Koordinaten.

Mein Problem ist jetzt, das sich die Figur beim "negativ" Bewegen immer um 1 Feld weniger nach hinten/unten bewegt als sie es sollte.

Ich habe schon unzählige Methoden durch und das ist eine davon. Ich probierte einfach immer wieder das "aktuelle" Feld als Startposition zu übergeben und mich dann weiter durchzuhangeln. Selbe ergebniss wie oben, es fehlt IMMER ein Feld.... habt ihr eine Ahnung, oder sowas schonmal gemacht  ich wäre 1000 mal dankbar.

Eine andere Frage wäre, das ist ja Frameindependent Movement. Aber wie schaffe ich es jetzt, das sich die Figur auch wirklich auf dem "Feld" bewegt und nicht ein paar Pixel weiter link/rechts oder wo anders daneben befindet? Man merkt da besonders, wenn das Spiel ruckelt und die "Sprünge"/Frame besonders groß werden.

Mfg
Oliver


----------



## Fu3L (25. Jan 2012)

Bist du sicher, dass wir es ohne die Klasse PathFinder lösen können?^^

Hast du denn einen vorgeschriebenen Weg für die Kreaturen oder können diese sich frei bewegen?

PS: Der Titel ist im Übrigen nicht besonders günstig... Wer keine Ahnung von Android hat (so wie ich), wird nicht unbedingt reinsehen und es hat ja wahrscheinlich GAR nichts mit Android zu tun^^


----------



## HimBromBeere (25. Jan 2012)

Zu dem Problem mit der Framerate lässt sich eine einfache Lösung finden: du musst die Bewegung deiner Objekte (bei dir die Gegner) an deine aktuelle Framerate anpassen. Das bedeutet, dass du messen musst, wie lange ein Schleifendurchlauf deiner Spielschleife dauert. Jetzt musst du halt die Veränderung der x/x-Koordinaten der Gegner an diese Zeit anpassen (du kennst ja das gute alte 
	
	
	
	





```
v = s / t
```
 bzw. 
	
	
	
	





```
s = v * t
```
)...


----------



## Titanpharao (25. Jan 2012)

Hallo Fu3L,

ja danke für den Hinweis mit dem Themen Namen, kann ich wohl leider nicht mehr ändern. (Wollte auch den Quellcode nochmal etwas aufräumen, nachhinein editieren geht wohl nicht?)

Die Klasse AStarPathFinder findet man im Internet  

AStarPathFinder (Slick - The 2D Library)

Sie liefert einfach nur einen Pfad zurück, der eine ArrayListe mit Wegpunkten enthält.
Wobei StartX,StartY,EndX,EndY als Parameter in Form eines Integers übergeben werden.

Äh die Figuren können sich frei bewegen. Sie werden halt von den Towern geblockt und der AStarPathFinder findet mir den  Weg 

Oder hat jemand mal ein Beispiel wie man das mit OpenGL macht? In dem Buch was ich habe, steht nur "freie" Bewegung drin, keine wie man Units direkt auf Tiles bewegt. Möglichst so, das sie sich exakt in der Mitte aufhalten bzw das rückwärstlaufen Problem.


----------



## Titanpharao (25. Jan 2012)

Habs jetzt erstmal so hinbekommen, nicht schön, aber besser als nichts.


```
public class Creep extends GameObject{

	private final AStarPathFinder finder;
	public final Vector2D velocity=new Vector2D();
	public static final float CREEP_VELOCITY=100f;
	public static final int FINAL_ABS_POSITION_X=8;
	public static final int FINAL_ABS_POSITION_Y=2;
	public Path path=null;
	float moveDistance=0;

	public Creep(float x,float y,float width,float height,AStarPathFinder finder){
		super(x,y,width,height);
		this.finder=finder;
	}

	public void setAbsolutePosition(int x,int y){
		path=finder.findPath(x,y,FINAL_ABS_POSITION_X,FINAL_ABS_POSITION_Y);
		fromPathToVelocity(0);
	}

	public void update(float deltaTime){
		moveDistance=moveDistance+deltaTime*CREEP_VELOCITY;
		fromPathToVelocity((int)(moveDistance/96));
		position.add(velocity.x*deltaTime,velocity.y*deltaTime);
		if(position.x<0)
			position.x=0;
		if(position.y<0)
			position.y=0;
	}

	public void fromPathToVelocity(int stepCount){
		if(path!=null){
			Step step=path.getStep(stepCount);
			int absX=step.getX();
			int absY=step.getY();
			step=path.getStep(++stepCount);
			int stepX=step.getX();
			int stepY=step.getY();
			if(stepX>absX&&stepY==absY){
				velocity.set(CREEP_VELOCITY,0);
			}else if(stepX==absX&&stepY<absY){
				velocity.set(0,-CREEP_VELOCITY);
			}else if(stepX<absX&&stepY==absY){
				velocity.set(-CREEP_VELOCITY,0);
			}else if(stepX==absX&&stepY>absY){
				velocity.set(0,CREEP_VELOCITY);
			}
		}else
			velocity.set(0,0);
	}
}
```


----------



## HimBromBeere (27. Jan 2012)

Wenn ich das richtig in Erinnerung hab, leifert A* doch immer den kürzesten Weg zwischen zwei Knoten zurück? Ist das der Sinn bei deinem Spiel? Bei den TowerDefense-Spielen, die ich kenne, werden die Laufwege immer zufällig ausgewählt (natürlich nur nicht zurück^^), das muss aber nicht zwingend der kürzeste sein.


----------

