Avatar of logicallayer
logicallayer

asked on 

moving ball using ACCELEROMETER sensor is lagging...why?

Hi,

I'm somehow new to android as I'm trying to make a very simple game that relys on moving the ball or circle based on the tilting of the cell phone, the movement works good maybe there is a room for improvement to get better accuracy but doesn't really concerns me for now

my problem is that the circle lags while it's moving, strangely I know I played alot of games before that are similar on my phone and it suppose to be able to handle such a simple game

I would guess that my problem is the way I'm listening to the sensor that is causing the lag but I don't know how to fix, can someone give some hints please?

there are some extra texts in the screen as I was doing some testing with them feel free to ignore them...
package org.example.sensortesty;

import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;



public class sensorTesty extends Activity implements SensorEventListener {
	public float x  ;
	public float y ;
	public float z;
	public int r;
	 float sensX = 0;
	 float sensY = 0;
	 float sensZ = 0;
	 
	 float x_ax = 90;
	 float y_ax = 90;

	
	/** Called when the activity is first created. */
	SensorManager sensorManager = null;

	// for accelerometer values
	TextView outputX;

	TextView outputY;
	TextView outputZ;

	// for orientation values

	TextView outputX2;
	TextView outputY2;
	TextView outputZ2;
	
	
	
		
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
		setContentView(R.layout.main);
		setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

	//	FrameLayout main = (FrameLayout) findViewById(R.id.main_view); 
		// main.addView(new Ball(this,50,50,25));
	}

		// just some for data output

		
	
	
	@Override
	protected void onResume() {
		super.onResume();
		sensorManager.registerListener(this,
				sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
				SensorManager.SENSOR_DELAY_GAME);

		sensorManager.registerListener(this,
				sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
				SensorManager.SENSOR_ORIENTATION);
	}

	@Override
	protected void onStop() {
		super.onStop();
		sensorManager.unregisterListener(this,
				sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER));
		sensorManager.unregisterListener(this,
				sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION));
	}

	
	public void onSensorChanged(SensorEvent event) {
		 synchronized (this) {
			switch (event.sensor.getType()) {
			case Sensor.TYPE_ACCELEROMETER:
				outputX = (TextView) findViewById(R.id.TextView01);	
				outputY = (TextView) findViewById(R.id.TextView02);
				outputZ = (TextView) findViewById(R.id.TextView03);

				outputX2 = (TextView) findViewById(R.id.TextView04);
				outputY2 = (TextView) findViewById(R.id.TextView05);
				outputZ2 = (TextView) findViewById(R.id.TextView06);

				 x = event.values[0];
                 y = event.values[1];
                 z = event.values[2];
                 if(z>2){
                 
                
                	 outputX.setText("Face Up");
                    
                	
                 }else if(z<-2){
                     outputX.setText("Face Down");
                	 
                 
                 }
                 if(x>1){
                     
                outputX.setText("Left Side");
                
                if(x_ax > 20)
                	 x_ax = x_ax - 10;
                 
                 }else if(x<-1){
                     outputX.setText("Right Side");
                	 if(x_ax < 300)
                     x_ax = x_ax + 10;
                 }
                 
                 if(y>1){
                	 
                     outputX.setText("Standing Up");
                     if(y_ax < 370)
                     y_ax = y_ax + 10;
        
                 }
                 else if(y<-1){
                    
                	 outputX.setText("On Head");
                	 
                	 if(y_ax > 20)
                	 y_ax = y_ax - 10;
                	 
                 }else{
                     outputX.setText("In Between");
                 }
				/*
			if( event.values[0] > 9)
			{
			sensX = event.values[0];
			x = x + 10;	
			}
			
			else if(event.values[0] < -9)
			{
			sensX = event.values[0];
			x = x - 10;
			}
			
			if(event.values[1] > 9)
			{
				sensY = event.values[1];
				y = y + 10;
			}
			
			else if( event.values[1] < -9)
			{
				sensY = event.values[1];
				y = y - 10;
			}
			

			if(sensZ > event.values[2])
			{
				sensZ = event.values[2];
				z = z + 10;
			}
			
			else if(sensZ < event.values[2])
			{
				sensZ = event.values[2];
				z = z - 10;
			}
*/
			
				
			FrameLayout main = (FrameLayout) findViewById(R.id.main_view); 
			main.removeAllViews();
			 main.addView(new Ball(this,x_ax,y_ax,25));
			
			
			
				//circle.moveTo(x, y);
			//main.addView(new Ball(this,40,40,25));
				break;

			case Sensor.TYPE_ORIENTATION:
				//x = event.values[0];
			//	y = event.values[1];
				
				//circle.moveTo(x, y);
				//outputX2.setText("x:" + Float.toString(event.values[0]));
				//outputY2.setText("y:" + Float.toString(event.values[1]));
				//outputZ2.setText("z:" + Float.toString(event.values[2]));
				break;
			}
		}
	}

	@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy) {
		// TODO Auto-generated method stub

	}
	
}

Open in new window

package org.example.sensortesty;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.View;

public class Ball extends View {

	 private float x;
	    private float y;
	    private int r;
	    Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
	    
	    public Ball(Context context, float x, float y, int r) {
	        super(context);
	        mPaint.setColor(0xFFFF0000);
	        this.x = x;
	        this.y = y;
	        this.r = r;
}

		@Override
		protected void onDraw(Canvas canvas) {
		
				super.onDraw(canvas);
			   
			    canvas.drawCircle(x, y, r,mPaint);	
		}
		
}

Open in new window

Android

Avatar of undefined
Last Comment
Francisco Igor
ASKER CERTIFIED SOLUTION
Avatar of Francisco Igor
Francisco Igor
Flag of Canada image

Blurred text
THIS SOLUTION IS ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
Avatar of logicallayer
logicallayer

ASKER

I tried to use postinvalidate() to enforce onDraw again after the cords been changed but it doesn't work

can you take a look at the adjusted code please
package org.example.sensortesty;

import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;



public class sensorTesty extends Activity implements SensorEventListener {
	public float x  ;
	public float y ;
	public float z;
	public int r;
	 float sensX = 0;
	 float sensY = 0;
	 float sensZ = 0;
	 
	 float x_ax = 90;
	 float y_ax = 90;

	
	/** Called when the activity is first created. */
	SensorManager sensorManager = null;

	// for accelerometer values
	TextView outputX;

	TextView outputY;
	TextView outputZ;

	// for orientation values

	TextView outputX2;
	TextView outputY2;
	TextView outputZ2;
	FrameLayout main;
	
	
		
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
		setContentView(R.layout.main);
		setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

		
		main = (FrameLayout) findViewById(R.id.main_view); 
		 main.addView(new Ball(this,x_ax,y_ax,25));
	}

		// just some for data output

		
	
	
	@Override
	protected void onResume() {
		super.onResume();
		sensorManager.registerListener(this,
				sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
				SensorManager.SENSOR_DELAY_GAME);

		sensorManager.registerListener(this,
				sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
				SensorManager.SENSOR_ORIENTATION);
	}

	@Override
	protected void onStop() {
		super.onStop();
		sensorManager.unregisterListener(this,
				sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER));
		sensorManager.unregisterListener(this,
				sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION));
	}

	
	public void onSensorChanged(SensorEvent event) {
		 synchronized (this) {
			switch (event.sensor.getType()) {
			case Sensor.TYPE_ACCELEROMETER:
				outputX = (TextView) findViewById(R.id.TextView01);	
				outputY = (TextView) findViewById(R.id.TextView02);
				outputZ = (TextView) findViewById(R.id.TextView03);

				outputX2 = (TextView) findViewById(R.id.TextView04);
				outputY2 = (TextView) findViewById(R.id.TextView05);
				outputZ2 = (TextView) findViewById(R.id.TextView06);

				 x = event.values[0];
                 y = event.values[1];
                 z = event.values[2];
                 if(z>2){
                 
                
                	 outputX.setText("Face Up");
                    
                	
                 }else if(z<-2){
                     outputX.setText("Face Down");
                	 
                 
                 }
                 if(x>1){
                     
                outputX.setText("Left Side");
                
                if(x_ax > 20)
                	 x_ax = x_ax - 10;
                 
                 }else if(x<-1){
                     outputX.setText("Right Side");
                	 if(x_ax < 300)
                     x_ax = x_ax + 10;
                 }
                 
                 if(y>1){
                	 
                     outputX.setText("Standing Up");
                     if(y_ax < 370)
                     y_ax = y_ax + 10;
        
                 }
                 else if(y<-1){
                    
                	 outputX.setText("On Head");
                	 
                	 if(y_ax > 20)
                	 y_ax = y_ax - 10;
                	 
                 }else{
                     outputX.setText("In Between");
                 }
				/*
			if( event.values[0] > 9)
			{
			sensX = event.values[0];
			x = x + 10;	
			}
			
			else if(event.values[0] < -9)
			{
			sensX = event.values[0];
			x = x - 10;
			}
			
			if(event.values[1] > 9)
			{
				sensY = event.values[1];
				y = y + 10;
			}
			
			else if( event.values[1] < -9)
			{
				sensY = event.values[1];
				y = y - 10;
			}
			

			if(sensZ > event.values[2])
			{
				sensZ = event.values[2];
				z = z + 10;
			}
			
			else if(sensZ < event.values[2])
			{
				sensZ = event.values[2];
				z = z - 10;
			}
*/
			
				
                 main.postInvalidate();
			//FrameLayout main = (FrameLayout) findViewById(R.id.main_view); 
			//main.removeAllViews();
			
			 //main.addView(new Ball(this,x_ax,y_ax,25));
			
			
			
			
				//circle.moveTo(x, y);
			//main.addView(new Ball(this,40,40,25));
				break;

			case Sensor.TYPE_ORIENTATION:
				//x = event.values[0];
			//	y = event.values[1];
				
				//circle.moveTo(x, y);
				//outputX2.setText("x:" + Float.toString(event.values[0]));
				//outputY2.setText("y:" + Float.toString(event.values[1]));
				//outputZ2.setText("z:" + Float.toString(event.values[2]));
				break;
			}
		}
	}

	@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy) {
		// TODO Auto-generated method stub

	}
	
}

Open in new window

Avatar of logicallayer
logicallayer

ASKER

main.postInvalidate();
SOLUTION
THIS SOLUTION IS ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
Avatar of logicallayer
logicallayer

ASKER

actually I got main.invalidate() to work as I found out that im recalling onDraw only with invalidate and the variable Im passing to onDraw changes only if I recall the object so I what I did changed x_ax and y_ax to public variables..

check the code if you want,

but still the circle is lagging even more than before this time Im not creating a new object everytime and still suffering from massive lag


package org.example.sensortesty;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.View;

public class Ball extends View {

	 //private float x;
	   // private float y;
	    private int r;
	    Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
	    
	    public Ball(Context context, float x, float y, int r) {
	        super(context);
	        mPaint.setColor(0xFFFF0000);
	        sensorTesty.x_ax = x;
	        sensorTesty.y_ax = y;
	        this.r = r;
	 
}

		@Override
		protected void onDraw(Canvas canvas) {
		
				super.onDraw(canvas);
			   
			    canvas.drawCircle(sensorTesty.x_ax, sensorTesty.y_ax, r,mPaint);	
		}
		
}

Open in new window

package org.example.sensortesty;

import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;



public class sensorTesty extends Activity implements SensorEventListener {
	public float x  ;
	public float y ;
	public float z;
	public int r;
	 float sensX = 0;
	 float sensY = 0;
	 float sensZ = 0;
	 
	public static float x_ax = 90;
	 public static float y_ax = 90;

	
	/** Called when the activity is first created. */
	SensorManager sensorManager = null;

	// for accelerometer values
	TextView outputX;

	TextView outputY;
	TextView outputZ;

	// for orientation values

	TextView outputX2;
	TextView outputY2;
	TextView outputZ2;
	FrameLayout main;
	
	
		
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
		setContentView(R.layout.main);
		setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

		
		main = (FrameLayout) findViewById(R.id.main_view); 
		 main.addView(new Ball(this,x_ax,y_ax,25));
		 
		 x_ax = 300;
		 y_ax = 300;
		 
		 main.invalidate();
	}

		// just some for data output

		
	
	
	@Override
	protected void onResume() {
		super.onResume();
		sensorManager.registerListener(this,
				sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
				SensorManager.SENSOR_DELAY_GAME);

		sensorManager.registerListener(this,
				sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
				SensorManager.SENSOR_ORIENTATION);
	}

	@Override
	protected void onStop() {
		super.onStop();
		sensorManager.unregisterListener(this,
				sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER));
		sensorManager.unregisterListener(this,
				sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION));
	}

	
	public void onSensorChanged(SensorEvent event) {
		 synchronized (this) {
			switch (event.sensor.getType()) {
			case Sensor.TYPE_ACCELEROMETER:
				outputX = (TextView) findViewById(R.id.TextView01);	
				outputY = (TextView) findViewById(R.id.TextView02);
				outputZ = (TextView) findViewById(R.id.TextView03);

				outputX2 = (TextView) findViewById(R.id.TextView04);
				outputY2 = (TextView) findViewById(R.id.TextView05);
				outputZ2 = (TextView) findViewById(R.id.TextView06);

				 x = event.values[0];
                 y = event.values[1];
                 z = event.values[2];
                 if(z>2){
                 
                
                	 outputX.setText("Face Up");
                    
                	
                 }else if(z<-2){
                     outputX.setText("Face Down");
                	 
                 
                 }
                 if(x>1){
                     
                outputX.setText("Left Side");
                
                if(x_ax > 20)
                	 x_ax = x_ax - 10;
                 
                 }else if(x<-1){
                     outputX.setText("Right Side");
                	 if(x_ax < 300)
                     x_ax = x_ax + 10;
                 }
                 
                 if(y>1){
                	 
                     outputX.setText("Standing Up");
                     if(y_ax < 370)
                     y_ax = y_ax + 10;
        
                 }
                 else if(y<-1){
                    
                	 outputX.setText("On Head");
                	 
                	 if(y_ax > 20)
                	 y_ax = y_ax - 10;
                	 
                 }else{
                     outputX.setText("In Between");
                 }
				/*
			if( event.values[0] > 9)
			{
			sensX = event.values[0];
			x = x + 10;	
			}
			
			else if(event.values[0] < -9)
			{
			sensX = event.values[0];
			x = x - 10;
			}
			
			if(event.values[1] > 9)
			{
				sensY = event.values[1];
				y = y + 10;
			}
			
			else if( event.values[1] < -9)
			{
				sensY = event.values[1];
				y = y - 10;
			}
			

			if(sensZ > event.values[2])
			{
				sensZ = event.values[2];
				z = z + 10;
			}
			
			else if(sensZ < event.values[2])
			{
				sensZ = event.values[2];
				z = z - 10;
			}
*/
			
				
                 main.invalidate();
			//FrameLayout main = (FrameLayout) findViewById(R.id.main_view); 
			//main.removeAllViews();
			
			 //main.addView(new Ball(this,x_ax,y_ax,25));
			
			
			
			
				//circle.moveTo(x, y);
			//main.addView(new Ball(this,40,40,25));
				break;

			case Sensor.TYPE_ORIENTATION:
				//x = event.values[0];
			//	y = event.values[1];
				
				//circle.moveTo(x, y);
				//outputX2.setText("x:" + Float.toString(event.values[0]));
				//outputY2.setText("y:" + Float.toString(event.values[1]));
				//outputZ2.setText("z:" + Float.toString(event.values[2]));
				break;
			}
		}
	}

	@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy) {
		// TODO Auto-generated method stub

	}
	
}

Open in new window

Avatar of logicallayer
logicallayer

ASKER

hmm, after careful checking I think it's not really a lag as much as it's the ball stops when it faceup and it seems like a lag

so I would say I got invalidate to work perfectly and that what I had problem with before,
problem solved

I have both invalidate() and postinvalidate() working, I know the first one goes for UI thread while the 2nd goes for non-UI thread...so why both are actually working for me?
Avatar of logicallayer
logicallayer

ASKER

btw many thanks for both of you
Avatar of logicallayer
logicallayer

ASKER

many thanks to you* (sorry typo earlier)
since the "onSensorChanged" event can send lots of events you probably are getting lags
when trying to invalidate in every sensor change and try to update all the TextViews in every loop.
Try to reduce the repetitive calls to invalidate and update textviews using a timer


long time=System.currentTimeMillis();


public void onSensorChanged(SensorEvent event) {
...

if (System.currentTimeMillis()-time>100){
  //invalidate view code
}
 time=System.currentTimeMillis();


...

}





 

Android
Android

Android is a mobile operating system developed by Google, based on the Linux kernel and designed primarily for touchscreen mobile devices such as smartphones and tablets. Android's user interface is based on direct manipulation, using touch gestures that loosely correspond to real-world actions, such as swiping, tapping and pinching, to manipulate on-screen objects, along with a virtual keyboard for text input. In addition to touchscreen devices, variants of Android are also used on notebooks, game consoles, digital cameras, televisions, automobiles and other electronics. Applications are usually developed in Java programming language using the Android software development kit (SDK), but other development environments are also available, including Delphi, Ruby and Visual Studio (using C++).

7K
Questions
--
Followers
--
Top Experts
Get a personalized solution from industry experts
Ask the experts
Read over 600 more reviews

TRUSTED BY

IBM logoIntel logoMicrosoft logoUbisoft logoSAP logo
Qualcomm logoCitrix Systems logoWorkday logoErnst & Young logo
High performer badgeUsers love us badge
LinkedIn logoFacebook logoX logoInstagram logoTikTok logoYouTube logo