i am trying to move windows cursor with android phone accelerometer, but i don't know how to properly use data to move cursor smoothly.
I use wifi to transfer data from phone to laptop.
Here is some code without wifi and socket transfer code, please give me some idea or correct my code.
Android:
onCreate:
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
I am using only X and Y coordinates:
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
x = event.values[0];
y = event.values[1];
Then i use this function in windows, that moves cursor from one to other position by steps:
Params: x1,x2 - from position, x2,y2 - to position, t - time, n - steps
public void mouseGlide(int x1, int y1, int x2, int y2, int t, int n) {
try {
Robot r = new Robot();
double dx = (x2 - x1) / ((double) n);
double dy = (y2 - y1) / ((double) n);
double dt = t / ((double) n);
for (int step = 1; step <= n; step++) {
Thread.sleep((int) dt);
r.mouseMove((int) (x1 + dx * step), (int) (y1 + dy * step));
}
} catch (Exception e) {
e.printStackTrace();
}
}
Basically i want to use phone tilt to move cursor as same as when i use mouse, photoshere in camera apps moves smoothly.
I do not know how to do it.
Related
I need to check if the mobile goes to the horizontal position (no landscape, I mean like you place it on the table).
I know I have to use "SensorEventListener" interface and the "onSensorChanged" event, but I am not able to get an example to howto check the mobile position.
#Override
public void onSensorChanged(SensorEvent event) {
//
}
Try this:
#Override
public void onSensorChanged(SensorEvent event) {
float[] values = event.values;
float x = values[0];
float y = values[1];
float z = values[2];
float norm =(float) Math.sqrt(x * x + y * y + z * z);
// Normalize the accelerometer vector
x = (x / norm);
y = (y / norm);
z = (z / norm);
int inclination = (int) Math.round(Math.toDegrees(Math.acos(z)));
if (inclination < 25 || inclination > 155)
{
// device is horiontal
Toast.makeText(this,"device horiontal !",Toast.LENGTH_SHORT).show();
}
}
I want to perform some activity when the user lifts the phone from a flat surface. The method I am using right now is detect shake motion using phone's Accelerometer using the following code:
sensorMan = (SensorManager) getSystemService(SENSOR_SERVICE);
accelerometer = sensorMan.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorMan.registerListener(this, accelerometer, SensorManager.SENSOR_STATUS_ACCURACY_HIGH);
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
mGravity = event.values.clone();
// Shake detection
float x = mGravity[0];
float y = mGravity[1];
float z = mGravity[2];
mAccelLast = mAccelCurrent;
mAccelCurrent = FloatMath.sqrt(x * x + y * y + z * z);
float delta = mAccelCurrent - mAccelLast;
mAccel = mAccel * 0.9f + delta;
if (mAccel > 0.9) {
//Perform certain tasks.
}
}
The issue I am facing with this code is the 0.9f threshold is reached sometimes even if the phone is still on the flat surface. I tried logging the mAccel value and found it to be rannging from 9.0 to 0.4 even when the phone is not even touched. Is there any guaranteed way to detect the phone's lift movement?
Solved the issue. All I wanted to do was to check for the "Y" value stated in the question and check if the value was greater than 1.0.
Note that, if the phone is kept in vertical position the Y is always around 9.8 but in such cases you can check for X instead. In my case user had to lift the phone and somewhen he will tilt the phone so I put a check for if(y >= 1.0 && y <= 2.0);
EDIT : UPDATED CODE
#Override
public void onSensorChanged(SensorEvent event) {
try {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
mGravity = event.values.clone();
// Shake detection
float x = mGravity[0];
float y = mGravity[1];
float z = mGravity[2];
float yAbs = Math.abs(mGravity[1]);
mAccelLast = mAccelCurrent;
mAccelCurrent = FloatMath.sqrt(x * x + y * y + z * z);
float delta = mAccelCurrent - mAccelLast;
mAccel = mAccel * 0.9f + delta;
if (yAbs > 2.0 && yAbs < 4.0 && !isAlerted() && !isCallActive()) {
alert();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
I would add the Gyroscope into the detection routine too.
The Phone gets Accelerated AND gets up from x=0 y=0 z=0 to, lets say y=120, that's the Trigger.
Look here
for Infos how to using it.
Another Sensor for lifting detection would be the Proximity Sensor, when the Phone lays flat on the Desk dinstance would be 0, if its picked up that value would raise quickly
Using the example with the bucket I am trying instead of using the
if(Gdx.input.isTouched()) {
Vector3 touchPos = new Vector3();
touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);
to use touchUp and touchDown.
So, in order to use them ,I define :
Vector2 position = new Vector2();
Vector2 velocity = new Vector2();
and then :
public boolean touchDown(int x, int y, int pointer, int button) {
if (x < 800 / 2 && y > 480 / 2) {
//here?? for left movement
}
if (x > 800 / 2 && y > 480 / 2) {
//here?? for right movement
}
return true;
}
Generally , I understand that I have a position and a velocity.And I must update the position related to velocity ,but I can't figure how.
You must update the position of your object every frame using the deltatime and the velocity vector.
Something like this(in render):
position.set(position.x+velocity.x*delta, position.y+velocity.y*delta);
And:
public boolean touchDown(int x, int y, int pointer, int button) {
if (x < 800 / 2 && y > 480 / 2) {
//here?? for left movement
velocity.x = -10;
}
if (x > 800 / 2 && y > 480 / 2) {
//here?? for right movement
velocity.x = 10;
}
return true;
}
public boolean touchUp(int x, int y, int pointer, int button) {
velocity.x = 0;
}
This may be an easy question, but I'm stuck. I am trying to implement the "shake to erase" feature in a drawing program (simple paint app). I can't get it to work. Here's my code:
private final SensorEventListener mSensorListener = new SensorEventListener() {
public void onSensorChanged(SensorEvent se) {
float x = se.values[0];
float y = se.values[1];
float z = se.values[2];
mAccelLast = mAccelCurrent;
mAccelCurrent = (float) Math.sqrt((double) (x*x + y*y + z*z));
float delta = mAccelCurrent - mAccelLast;
mAccel = mAccel * 0.9f + delta; // perform low-cut filter
if (mAccel > 2) {
mView.onDraw(mCanvas);
mCanvas.drawBitmap(cache, 0, 0, new Paint(Paint.DITHER_FLAG));
}
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
The SensorEventListener is based off of this example. I make it into the if statement, but the canvas won't reset until after I've touched the screen (a new touch event).
I'd like the canvas to reset/erase during the shake event, without any further prompts from the user necessary.
Any help would be wonderful, thank you!
You might have to call invalidate on the graphics object to get it to redraw.
Hope that helps!
http://developer.android.com/guide/topics/graphics/index.html
I'm working on a game which will use projectiles. So I've made a Projectile class and a new instance is created when the user touches the screen:
#Override
public boolean onTouch(View v, MotionEvent e){
float touch_x = e.getX();
float touch_y = e.getY();
new Projectile(touch_x, touch_y);
}
And the Projectile class:
public class Projectile{
float target_x;
float target_y;
Path line;
public Projectile(float x, float y){
target_x = x;
target_y = y;
line = new Path();
line.moveTo(MyGame.mPlayerXPos, MyGame.mPlayerYPos);
line.lineTo(target_x, target_y);
}
}
So this makes a Path with 2 points, the player's position and and touch coords. My question is - How can you access points on this line? For example, if I wanted to get the x,y coords of the Projectile at the half point of the line, or the point the Projectile would be at after 100 ticks (moving at a speed of X pixels/tick)?
I also need the Projectile to continue moving after it reaches the final point.. do I need to use line.addPath(line) to keep extending the Path?
EDIT
I managed to get the Projectiles moving in a straight line, but they're going in strange directions. I had to fudge some code up:
private void moveProjectiles(){
ListIterator<Projectile> it = Registry.proj.listIterator();
while ( it.hasNext() ){
Projectile p = it.next();
p.TimeAlive++;
double dist = p.TimeAlive * p.Speed;
float dx = (float) (Math.cos(p.Angle) * dist);
float dy = (float) (Math.sin(p.Angle) * dist);
p.xPos += dx;
p.yPos += -dy;
}
}
The Angle must be the problem.. I'm using this method, which works perfectly:
private double getDegreesFromTouchEvent(float x, float y){
double delta_x = x - mCanvasWidth/2;
double delta_y = mCanvasHeight/2 - y;
double radians = Math.atan2(delta_y, delta_x);
return Math.toDegrees(radians);
}
However, it returns 0-180 for touches above the center of the screen, and 0 to -180 for touches below. Is this a problem?
The best way to model this is with parametric equations. No need to use trig functions.
class Path {
private final float x1,y1,x2,y2,distance;
public Path( float x1, float y1, float x2, float y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.distance = Math.sqrt( (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
}
public Point position( float t) {
return new Point( (1-t)*x1 + t*x2,
(1-t)*y1 + t*y2);
}
public Point position( float ticks, float speed) {
float t = ticks * speed / distance;
return position( t);
}
}
Path p = new Path(...);
// get halfway point
p.position( 0.5);
// get position after 100 ticks at 1.5 pixels per tick
p.position( 100, 1.5);
From geometry, if it's a straight line you can calculate any point on it by using polar coordinates.
If you find the angle of the line:
ang = arctan((target_y - player_y) / (target_x - player_x))
Then any point on the line can be found using trig:
x = cos(ang) * dist_along_line
y = sin(ang) * dist_along_line
If you wanted the midpoint, then you just take dist_along_line to be half the length of the line:
dist_along_line = line_length / 2 = (sqrt((target_y - player_y)^2 + (target_x - player_x)^2)) / 2
If you wanted to consider the point after 100 ticks, moving at a speed of X pixels / tick:
dist_along_line = 100 * X
Hopefully someone can comment on a way to do this more directly using the android libs.
First of all, the Path class is to be used for drawing, not for calculation of the projectile location.
So your Projectile class could have the following attributes:
float positionX;
float positionY;
float velocityX;
float velocityY;
The velocity is calculated from the targetX, targetY, playerX and playerY like so:
float distance = sqrt(pow(targetX - playerX, 2)+pow(targetY - playerY, 2))
velocityX = (targetX - playerX) * speed / distance;
velocityY = (targetY - playerY) * speed / distance;
Your position after 20 ticks is
x = positionX + 20 * velocityX;
y = positionY + 20 * velocityY;
The time it takes to reach terget is
ticksToTarget = distance / velocity;
Location of halp way point is
halfWayX = positionX + velocityX * (tickToTarget / 2);
halfWayY = positionY + velocityY * (tickToTarget / 2);