Aloha android-developers Community,
Ich beschäftige mich seit einiger Zeit mit Java und Android und hab bin jetzt dabei ein kleines 2D Android Spiel zu entwickeln.
So
weit so gut, das Spiel besteht im wesentlichen daraus, dass der Spieler
ein Objekt(character) lenkt und einem Anderem Objekt(Sprite) ausweichen
muss. also sehr einfach.
Zum Laufen hab ich schon recht viel
bekommen: Layout,Musik, Automatische Bewegung von Sprite, interaktive
Bewegung von Character,usw.
Nun das Problem: Die Kolissions Erkennung
Jetzt denken einige bestimmt, wie einfach:
jedem Objekt ein Rechteck zuordnen und per intersect-Methode kolissionen überprüfen...
die Kolissionerkennung hab ich dabei in einen extra Thread ausgelagert.
So hab ich es auch gemacht, aber es funktioniert nicht wie gewollt.
Das Problem liegt vermutlich daran:
[Blockierte Grafik: http://s14.directupload.net/images/140520/56bi53o9.jpg]
Intersect zwischen Character(orange) und Sprite(gruen) wird ausgeführt und Kolission erkannt;
KolissionThread führt aus:
public class KolissionsThread extends Thread {
private boolean x=true;
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
if(Character.rect.intersect(Sprite.rect2)){
MainActivity.handir.sendEmptyMessage(1);
GameLoopThread.setRunning(false);
}
}
}
Alles anzeigen
handir ist der Handler, der bei Kolission die GameOver Activity startet.
er führt aus:
public void handleMessage(Message msg) {
Intent inti = new Intent(getApplicationContext(), GameOver.class);
startActivity(inti);
this.finish();
super.handleMessage(msg);
}
Alles anzeigen
Soweit so gut, Kolission erkannt, Intent gesendet und Gameover gestartet....
Nur
brauch der Intent dermaßig lange(1,5s) um die Activity zustarten, dass
es dazu kommt das trotz Kolission, das Bild erneut gezeichnet wird:
[Blockierte Grafik: http://s14.directupload.net/images/140520/evse7b7b.jpg]
Es entsteht also eine überlappung, die sehr schlampig wirkt.
das
komische: bei einer kollision wird der GameLoopThread, der für das
aufrufen der ondraw Methode der SurfaceView zuständig ist gestoppt(
siehe oben "GameLoopThread.setRunning(false);"), dennoch wird es noch
ein letztes mal gezeichnet.
ich weiß nicht was ich noch anders
machen kann, wenn bei einer Kolission GameLoopThread.sleep() als erstes
aufgerufen wird, funktioniert die Kollision tadelos, wenn jedoch die
Sleep Zeit vorbei ist und der Intent gesendet wird entsteht wieder das
bekannte Problem des weiterzeichnens.
Ich hoffe das war nicht zu verwirrend, zum besseren Verständniss hier:
der Code des GameLoopThreads:
import android.graphics.Canvas;
public class GameLoopThread extends Thread {
private static GameView theView;
static KolissionsThread kolli;
private static boolean isRunning = false;
static final long FPS=60;
public GameLoopThread(GameView theView) {
this.theView = theView;
}
public static void setRunning(boolean run) {
isRunning = run;
}
@Override
public void run() {
long TPS=1000/FPS;
long startTime,sleepTime;
while (isRunning) {
Canvas theCanvas = null;
startTime=System.currentTimeMillis();
try {
theCanvas = theView.getHolder().lockCanvas();
synchronized (theView.getHolder()) {
theView.onDraw(theCanvas);
}
} finally {
if (theCanvas != null) {
theView.getHolder().unlockCanvasAndPost(theCanvas);
}
sleepTime=TPS-(System.currentTimeMillis()-startTime);
try{
if(sleepTime>0){
sleep(sleepTime);}
else
sleep(10);
}
catch (Exception e){
}
}
}
}
public static void los() {
// TODO Auto-generated method stub
kolli=new KolissionsThread();
kolli.run();
}
}
Alles anzeigen
und der SurfaceView mit dem Canvas:
public GameView(Context context) {
super(context);
gameloopthread = new GameLoopThread(this);
maini=(MainActivity) context;
surfaceHolder = getHolder();
bmphg=BitmapFactory.decodeResource(getResources(), R.drawable.hintergrund2);
surfaceHolder.addCallback(new SurfaceHolder.Callback() {
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
gameloopthread.setRunning(false);
while (retry) {
try {
gameloopthread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
gameloopthread.setRunning(true);
gameloopthread.start();
}
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
// TODO Auto-generated method stub
}
});
}
@Override
protected void onDraw(Canvas canvas) {
time = (System.currentTimeMillis() - time_start) / 1000d;
Paint pinselrot=new Paint();
pinselrot.setColor(Color.RED);
Paint pinsel=new Paint();
pinsel.setAlpha(0);
pinselrot.setAlpha(0);
canvas.drawBitmap(bmphg, 0, 0, null);
this.setOnTouchListener(this);
Character.verschieben();
boolean charr = true;
Paint pinsel2= new Paint();
pinsel2.setColor(Color.BLACK);
pinsel2.setStrokeWidth(50);
float textSize = pinsel2.getTextSize();
pinsel2.setTextSize(textSize*4);
if (charr == true) {
bmp2 = BitmapFactory.decodeResource(getResources(),
R.drawable.gruen);
character = new Character(bmp2, this);
character.onDraw(canvas);
charr = false;
}
if (createSprites == true) {
initialSprites();
}
for (Sprite sprite : spriteList) {
sprite.onDraw(canvas);
}
canvas.drawRect(Character.rect, pinselrot);
canvas.drawRect(Sprite.rect2,pinsel);
canvas.drawText(""+ time, bmphg.getWidth()-150,50 , pinsel2);
GameLoopThread.los();
}
Alles anzeigen
Ich vermute das man das SurfaceView irgendwie dazubringen müsste sofort stehenzubleiben und nichts mehr zu zeichnen,aber egal...
Hat jemand eine Idee wie man das Problem lösen kann?
Grüße Jan