kostenloser Webspace werbefrei: lima-city


Android - Objekt bewegen mit Hilfe des Bewegungssensors

lima-cityForumProgrammiersprachenJava

  1. Autor dieses Themas

    ultimate-bravery

    ultimate-bravery hat kostenlosen Webspace.

    Hallo zusammen,

    ich versuche gerade einen Kreis, der am Anfang in der Mitte des Bildschirms ist, durch Bewegen des Smartphones nach links oder nach rechts zu bewegen.

    Ich präsentiere euch einfach mal meinen Code und fange mit der Activity Klasse an:

    import android.app.Activity;
    import android.hardware.SensorManager;
    import android.os.Bundle;
    import android.view.WindowManager;
    
    public class GameActivity extends Activity {
    
    	SensorManager sm;
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    		sm = (SensorManager) getSystemService(SENSOR_SERVICE);
    		setContentView(new GameView(this, sm));
    	}
    
    }

    Dort wird ein SensorManager erstellt, der an die GameView Klasse, welche als Layout genutzt wird, weitergegeben wird. Das habe ich so gemacht, da ich es nicht hinbekommen habe, den SensorManager in der GameView Klasse zu erstellen. Hier ist die GameView Klasse:

    import java.util.ArrayList;
    import java.util.Random;
    
    import android.annotation.SuppressLint;
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Point;
    import android.hardware.Sensor;
    import android.hardware.SensorEvent;
    import android.hardware.SensorEventListener;
    import android.hardware.SensorManager;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    
    public class GameView extends SurfaceView implements SensorEventListener {
    
    	private SurfaceHolder surfaceHolder;
    	private GameLoopThread theGameLoopThread;
    	private Figur spielfigur;
    	
    	private Sensor accelerometer;
    
    	@SuppressLint("WrongCall")
    	public GameView(Context context, SensorManager sm) {
    		super(context);
    		
    		accelerometer = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
            	sm.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
            
    		theGameLoopThread = new GameLoopThread(this);
    		surfaceHolder = getHolder();
    		surfaceHolder.addCallback(new SurfaceHolder.Callback() {
    
    			public void surfaceDestroyed(SurfaceHolder holder) {
    				boolean retry = true;
    				theGameLoopThread.setRunning(false);
    				while (retry) {
    					try {
    						theGameLoopThread.join();
    						retry = false;
    					} catch (InterruptedException e) {
    
    					}
    				}
    
    			}
    
    			public void surfaceCreated(SurfaceHolder holder) {
    				theGameLoopThread.setRunning(true);
    				theGameLoopThread.start();
    			}
    
    			public void surfaceChanged(SurfaceHolder holder, int format,
    					int width, int height) {
    
    			}
    		});
    		spielfigur = new Figur(this);
    	}
    
    	@SuppressLint("WrongCall")
    	@Override
    	protected void onDraw(Canvas canvas) {
    		canvas.drawColor(Color.DKGRAY);
    		spielfigur.drawMe(canvas);
    	}
    
    	@Override
    	public void onSensorChanged(SensorEvent event) {
    		try {
    			Thread.sleep(16);
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		int moveX =(int) -event.values[0];
    		spielfigur.setXSpeed(moveX*20);
    	}
    
    	@Override
    	public void onAccuracyChanged(Sensor sensor, int accuracy) {
    		// TODO Auto-generated method stub
    		
    	}
    
    }

    Die Klasse erbt von der Klasse SurfaceView und implementiert das Interface SensorEventListener. Dort werden halt die Bewegungen wahr genommen und dementsprechend die Bewegungsgeschwindigkeit angepasst. Außerdem sorgt sie für das Zeichnen. Damit der Kreis sich schneller bewegt, multipliziere ich den x Wert des Sensors noch mit 20. Hier ist jetzt meine Klasse für den Kreis bzw für die Figur:

    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Point;
    
    public class Figur implements Drawable {
    	
    	private float x;
    	private float y;
    	private float radius = 20;
    	private int xSpeed = 0;
    	private Paint paint;
    	private GameView gameView;
    	private boolean oneTime = false;
    	
    	public Figur(GameView gameView){
    		this.gameView = gameView;
    		
    		paint = new Paint();
            	paint.setStyle(Paint.Style.FILL);
            	paint.setColor(Color.RED);
    	}
    
    	@Override
    	public void drawMe(Canvas canvas) {
    		if(!oneTime){
    			oneTime = true;
    			x = canvas.getWidth()/2;
    			y = canvas.getHeight()/2;
    		}
    		moveAndCheckCollision();
    		canvas.drawCircle(x, y, radius, paint);
    	}
    	
    	public void moveAndCheckCollision() {
    		// Kollision mit Rand
    		if(x > gameView.getWidth() - radius - xSpeed || x - radius + xSpeed < 0){
    			xSpeed = 0;
    		}
    		x += xSpeed;
    	}
    	
    	public void setXSpeed(int xSpeed){
    		this.xSpeed = xSpeed;
    	}
    
    }

    Dann hier noch die Thread Klasse:

    import android.annotation.SuppressLint;
    import android.graphics.Canvas;
    
    public class GameLoopThread extends Thread {
    	static final long FPS = 20;
        private GameView theView;
        private boolean isRunning = false;
     
        public GameLoopThread(GameView theView) {
            this.theView = theView;
        }
     
        public void setRunning(boolean run) {
            isRunning = run;
        }
        
        @SuppressLint("WrongCall") 
        @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){
                	
                }
            }
        }
     
    }

    Den größten Teil davon, zum Beispiel die Thread Klasse oder die GameView Klasse habe ich aus einem Tutorial. Das mit dem Sensor und der Figur habe ich dann dazu gepackt. Ich bin jetzt noch nicht ganz zufrieden damit^^ Der Kreis bewegt sich zwar schon recht flüssig, aber es könnte noch besser gehen. Und wenn man das Handy sehr stark neigt, dann bleibt der Kreis schon etwas vor dem Bildschirmrand stehen, da die Geschwindigkeit ja dann ziemlich hoch ist und somit die if Abfrage in der moveAndCheckCollision() Methode eintrifft und die Geschwindigkeit auf 0 gesetzt wird. Was mich noch stört ist, das der Spielraum, in der die Geschwindigkeit 0 ist, sehr groß ist. Das heißt, ich kann das Handy in beide Richtungen um ca 10°-20° drehen, ohne dass sich der Kreis bewegt. Das sollte feiner werden, also er sollte sich schon früher bewegen.

    Ich würde mir also gerne Verbesserungsvorschläge von euch anhören, wie ich diese Bewegung optimieren könnte. Wäre cool wenn sich der ein oder andere mal Zeit nimmt und drüber guckt.

    Viele Grüße
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!