Accelerometer for android game can't move in the right way - android

i'm making a game with accelerometer feature, so that each time i turn my device to the left, the ship will bank left, and vice versa
the problem is that the ship keep moving left by itself
here's my code
public void onSensorChanged(SensorEvent event){
if(event.sensor.getType()==Sensor.TYPE_ACCELEROMETER){
float x = event.values[0];
deltaX = xBefore-x;
xBefore = x;
if(deltaX>0){//move right
SFEngine.playerFlightAction = SFEngine.PLAYER_LEFT_BANK_1;
}else{//move left
SFEngine.playerFlightAction =SFEngine.PLAYER_RIGHT_BANK_1;
}
}
}

You should not use any delta. Just check if x > 0, then move it to the left, else to the right
deltaX is not calculated well in your code. It does not consider that xBefore can be less than zero and current x is greater than zero (or other way round). Delta should be calculated using absolute value.
However I suppose that you really don't need any delta here. Just use x.

Related

Android - Acceleration down (smash)

Video explaining for those who does not understand
THIS ANSWER IS NOT CORRECTLY ANSWERED PLEASE TRY TO ANSWER IT WITH ANOTHER SOLUTION (100 Bounty is out of date)
Same question but better explained
This questions was accepted as a correct but it is not at all, I tried it with my old device ZTE and it worked most of time, but now I have a Samsung Galazy A5 2016 and it doesn't work, neither on a LG G3.
The thing is trying using Accelerometer and some Sensors I have to be able to detect any of those two moviments that I made on the Video.
There are two moviments :
Smashing it (with a little bit of velocity)
Free fall
I let you to decide and convince me what's the better option and EASIER one to do, with better I mean that works on most of devices.
A stationary device will have an gravity value of +9.81, which corresponds to the acceleration of the device (0 m/s2 minus the force of gravity, which is -9.81 m/s2). Thus if the device is moving downward from stationary then the gravity will be less than 9.81. A free fall device will have gravity equals 0.
Below is how to determine if the device starts moving downward. It will not be able to determine whether the device is moving downward if the device is already moving downward with constant speed, since in this case there is no acceleration downward and the gravity norm should be around 9.81.
You need to use TYPE_GRAVITY. If the device does not have TYPE_GRAVITY, then low pass filter TYPE_ACCELEROMETER to get the gravity vector.
As above a stationary device will have a gravity vector with norm equal 9.81. However, this value will vary slightly with devices. Thus you need first to determine this stationary gravity norm. You can do this by register for TYPE_GRAVITY or TYPE_ACCELEROMETER and ask the user to lay the device flat and then press a button. Once the button is pressed the app will calculate the norm of the gravity in onSensorChanged.
private float mStationaryGravityNorm;
private float mDeviation = 0.01;
private float mCount;
private boolean mIsCalculatingStationGravityNorm = true;
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener( {
#Override
public void onClick(View v) {
// register sensor
}
});
#Override
public void onSensorChanged(SensorEvent event) {
// Will average out 100 gravity values.
if (mIsCalculatingStationGravityNorm) {
if (mCount++ < 100) {
mStationaryGravityNorm += Math.sqrt(event.values[0] * event.values[0] + event.values[1] * event.values[1] + event.values[2] * event.values[2]);
} else {
mStationaryGravityNorm /= 100;
mIsCalculatingStationGravityNorm = false;
} else {
float gravityNorm = Math.sqrt(event.values[0] * event.values[0] + event.values[1] * event.values[1] + event.values[2] * event.values[2]);
if (gravityNorm < mStationaryGravityNorm - mDeviation) {
// moving down
}
}
PS For moving up an down you do want to calculate gravity. When the device is stationary, the gravity norm is approximately 9.81 (depending on device). Now if the device is moving down, there is an acceleration downward, thus the gravity norm will be less than 9.81 and if the device is moving up the gravity norm will be more than 9.81. So by comparing the gravity norm against this stationary gravity norm, you will know if the device moving up or down. This is independent of the device orientation. TYPE_GRAVITY will give better accuracy but if the device does not have this type then low pass filter TYPE_ACCELERATOR will give you the gravity vector.
if you want to see if the device is in free fall, you should check if the normal is closer to zero.
http://developer.android.com/guide/topics/sensors/sensors_motion.html
public void onSensorChanged(SensorEvent event) {
double noraml = Math.sqrt(Math.pow(event.values[0].getX(),2)+
Math.pow(event.values[1].getY(),2)+
Math.pow(event.values[2].getZ(),2));
if (normal < 0)
return true;
return false;
}

Detect if device has taken a turn using location service android

I want to detect if the user has taken a turn on the road while driving using the sensors on the android phone. How do I code this? I am collecting data live from all the sensors(accelerometer,location,rotation,geomagnetic) and storing them on the sd card. So now i just want to know whether the user has a taken a turn and in which direction he has turned.
I assume the registration of the sensor is done properly. You can detect the direction by using the orientation sensor (deprecated) as follows:
#Override
public void onSensorChanged(SensorEvent event) {
float azimuth_angle = event.values[0];
int precision = 2;
if (prevAzimuth - azimuth_angle < precision * -1)
Log.v("->", "RIGHT");
else if (prevAzimuth - azimuth_angle > precision)
Log.v("<-", "LEFT");
prevAzimuth = azimuth_angle;
}
Note: The variable of "prevAzimuth" is declared as global. You can change "precision" value to whatever you want. We need this value because we do not want to see output after each trivial change in azimuth angle. However, too large precision gives imprecise results. To me, "2" is optimum.
If you are tracking location coordinates, you can also track shifts between the angle from previous locations.
angle = arctan((Y2 - Y1) / (X2 - X1)) * 180 / PI
See this answer for calculating x and y.
Decision to use sensor values is based on an unrealistic assumption that the device is never rotated with respect to the vehicle.

Using accelerator sensor android to get Direction

I am trying to make a simple Android application, this application will get Direction when moving android device from right to left or when moving android device from Top to Button. the movement just in 2d for example android device on table or board. for example when the movement from right to left the The Left Value shell be true and right value shell False so on
Code of onCreate Method
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
tvLeft= (TextView) findViewById(R.id.textViewLeft);
tvRight= (TextView) findViewById(R.id.textViewRight);
tvTop= (TextView) findViewById(R.id.textViewTop);
tvButton= (TextView) findViewById(R.id.textViewBoutton);
}
Code of onSensorChanged Method
public void onSensorChanged(SensorEvent event) {
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
long curTime = System.currentTimeMillis();
if ((curTime - lastUpdate) > 100) {
lastUpdate = curTime;
float diffX=last_x-x;
float diffY=last_y-y;
Log.d("Mhd",Float.toString(diffX)+" X Diff");
Log.d("Mhd",Float.toString(diffY)+" y Diff");
diffX = Float.parseFloat(String.format("%1$,.1f", diffX));
diffY = Float.parseFloat(String.format("%1$,.1f", diffY));
if(x>last_x && Math.abs(diffX) > 0.1){
tvLeft.setText("T");
tvRight.setText("F");
}else if(x<last_x && Math.abs(diffX) > 0.1){
tvRight.setText("T");
tvLeft.setText("F");
}
if(y>last_y && Math.abs(diffY) > 0.1){
tvTop.setText("T");
tvButton.setText("F");
}else if(y<last_y && Math.abs(diffY) > 0.1)
tvButton.setText("T");
tvTop.setText("F");
}
last_x = x;
last_y = y;
last_z = z;
}
}
Finally the program dose not gives an error
but the generated data is not true and when the android device stable the data still
generated.
please any idea to improve my code.
You need to think about what an accelerometer is and what it does. It's basically a force meter. It detects a force on the device, and measures it. It always tells you the current level of force (which will actually never be 0 due to gravity, unless you're in outer space). It does not detect motion. It does not return values only when moved. It returns values every time its asked, which with SENSOR_DELAY_NORMAL means every few hundred milliseconds.
The data will never be 100% correct. The data will always have noise, because all physical sensors do. Reverbations from old forces, mild forces due to people walking around the room, your table being not 100% steady- the sensor will pick up all of those minor changes. It will also be wrong by some amount each time, because they're only so accurate. You need to look for large changes only, if you're looking for very small changes you need much better hardware than comes in phones.
Finally, it captures forces not motions. That means if you were to move the device at constant speed, there wouldn't be any change detected- an object at constant speed has no force applied to it. It will only catch changes in speed- accelerations and decelerations. You need to look for these rather than assuming a change means its moving. For example, moving the device left would see an acceleration to the left, followed by 0 acceletation, then an acceleration to the right (really a deceleration) as you stopped, followed by nothing.
You need to rework your whole approach. You need much, much higher noise thresholds, and you need to look for accelerations and decelerations to determine if it is moving, otherwise your deceleration will look like a move in the wrong direction. It's a lot more complicated than what you have here.

Perform multi click event on a single image in Android

suppose take my example as PIANO image..on every key press on its keyboard i want to perform a different event..now i am not able to get where to start this..
how to perform this in android..
take below image:
As you can see in the image i have an piano image..and drawn red and blue lines in some shape..now i want to perform different event for each shape on this image..
how can i do this in android programming..
This seems like a basic Collision Detection problem.
Basically what you want to do is of course listen to the screen touches and receive the X & Y of the touch location. (You can of course use multi-touch, just remember to do this for every touch)
When a touch appears you will calculate a bunch of containsRectanglePoint for each key on the image.
So basically you will split the image into a lot of rectangles like so.
(source: gyazo.com)
Then you check if the point contains any of the rectangles.
If the touch X & Y is inside either 1 or 2 then perform the event for that key.
If the touch X & Y is inside either 3, 4 or 5 the perform the event for that key.
If the touch X & Y is inside either 6 then perform the event for that key.
If the touch X & Y is inside either 7 then perform the event for that key.
You will of course do that for all the keys.
So thereby when a collision happens you look through all that.
Simple Rectangle vs Point Collision Detection
The following code checks for collision detection between a rectangle and a point. If the point is within the rectangles bounds then the method will return true. If not it returns false.
public static boolean containsRectanglePoint(double x, double y, double w, double h, double px, double py)
{
if (px < x) { return false; }
if (py < y) { return false; }
if (px > (x + w)) { return false; }
if (py > (y + h)) { return false; }
return true;
}
x = Rectangle X (or AABB Minimum X)
y = Rectangle Y (or AABB Minimum Y)
w = Rectangle Width (or AABB Maximum X - AABB Minimum X)
h = Rectangle Height (or AABB Maximum Y - AABB Minimum Y)
px = Point X
py = Point Y
In your case px & py is the location of the touch.
You could also use Java's standard Rectangle2D class, to both store and calculate the collisions, but that requires creating a lot of instances of the class, and it will be a lot cheaper, when we are talking about memory, to just store the coordinates and then use the function I provided to you.

Android orientation as steering - roll corrupting pitch?

I am working on a project which includes an Android application which is used for
controlling/steering.
Speed: When you tilt the phone forward/backwards (pitch) it simulates giving gas and breaking.
Direction: When you tilt the phone left/right (roll) it simulates steering to the left and right.
I have already written some code which seemed to work fine. But when I took a closer look, I found that some values are acting weird.
When I tilt the phone forward/backward to handle the speed it works perfect I get the expected speed and direction values. But when I tilt the phone to the left/right to handle the direction it seems to corrupt some values. When it is tilting to the left/right that doesn't only change the direction value (roll) but it also affects the speed value (pitch).
For extra information:
Programming for Android 2.2
Device is an Google Nexus One
Holding the device in portrait
The most relevant code I use to read the sensor values is as follows:
public void onSensorChanged(SensorEvent sensorEvent)
{
synchronized (this)
{
if (sensorEvent.sensor.getType() == Sensor.TYPE_ORIENTATION)
{
float azimuth = sensorEvent.values[0]; // azimuth rotation around the z-axis
float pitch = sensorEvent.values[1]; // pitch rotation around the x-axis
float roll = sensorEvent.values[2]; // roll rotation around the y-axis
System.out.println("pitch: " + pitch);
System.out.println("roll: " + roll);
System.out.println("--------------------");
// Convert the sensor values to the actual speed and direction values
float speed = (pitch * 2.222f) + 200;
float direction = roll * -2.222f;
So when I run the code, and I look at the printed values. When tilting the device left/right, it seems to affect the pitch value as well. How come? And how can I get the pure pitch value, when 'roll'-ing? So that tilting the phone to the left/right doesn't affect/corrupt the pitch value.
You could read up on Gimbal lock. That's bitten me before.

Categories

Resources