I want to move an image over the screen by the accelerometer detection, but the only example I found on is something like this:
public void onSensorChanged(SensorEvent event){
float x = event.values[0];
float y = event.values[1];
if (Math.abs(x) > Math.abs(y)) {
if (x < 0) {
image.setImageResource(R.drawable.right);
textView.setText("You tilt the device right");
}
if (x > 0) {
image.setImageResource(R.drawable.left);
textView.setText("You tilt the device left");
}
} else {
if (y < 0) {
image.setImageResource(R.drawable.up);
textView.setText("You tilt the device up");
}
if (y > 0) {
image.setImageResource(R.drawable.down);
textView.setText("You tilt the device down");
}
}
if (x > (-2) && x < (2) && y > (-2) && y < (2)) {
image.setImageResource(R.drawable.center);
textView.setText("Not tilt device");
}
}
That code only displays a different image depends on the tilt of the phone, but I want to move the same image like "a ball into the screen".
Related
I would like to detect using accelerometer if phone is moving up or down and how many times direction was changed.
I am using this code:
lastY = 0;
lastYChange = 0;
initialized = false;
...
if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null) {
accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
...
#Override
public void onSensorChanged(SensorEvent event) {
float y = event.values[1];
if (!initialized) {
lastY = y;
initialized = true;
}
else {
float yChange = lastY - y;
float deltaY = Math.abs(yChange);
if (deltaY < 2) {
deltaY = 0;
}
else {
if (lastYChange < 0 && yChange > 0) {
counter += 1;
textViewDirection.setText("Direction: Top");
textViewCounter.setText("Counter: " + counter);
}
else if (lastYChange > 0 && yChange < 0) {
counter += 1;
textViewDirection.setText("Direction: Bottom");
textViewCounter.setText("Counter: " + counter);
}
lastYChange = yChange;
}
lastY = y;
textViewAcceleration.setText("Acceleration is: " + deltaY);
}
}
So if I move phone in only one direction, for example top direction, counter should be increased by only 1, and textViewDirection should have value of "Direction: Top".
Instead, with this code counter is increased multiple times and textViewDirection is switching from "Direction: Top" and "Direction: Down".
Does anyone know to fix this? So that, for example, if I move phone up, then down, then up, counter should have value of 3, and textViewDirection should have value "Direction: Top", "Direction: Down" and "Direction: Top", respectively.
This is a possible accelerometer result when you move the sensor Unfortunately, y accelerometer waveform is not as straightforward to behave as you thought in your code. It oscillates a lot, e.g. when you stop the device
I am developing a Tetris for Android using C++ taking advantage of SDL2 portability, the thing is that i have a lot of delays when i get events from the touch interface, is like the the function SDL_PollEvent() doesn't work like on PC, i have wrote this on my getting events method.
float x = 0, y = 0;
while (SDL_PollEvent(&event)){
switch (event.type) {
case SDL_QUIT: { gameState = false; break;}
case SDL_FINGERDOWN: {
x = event.tfinger.x;
y = event.tfinger.y;
SDL_Log("\nDesplazamiento x: %f desplazamiento y: %f.\n", x, y);
window.get_AbsPixels(&x, &y);
if (x >= keys->U.getX() && x <= (keys->U.getX() + keys->U.getW()) &&
y >= keys->U.getY() && x <= keys->U.getY() + keys->U.getH())
return Up;
if (x >= keys->D.getX() && x <= (keys->D.getX() + keys->D.getW()) &&
y >= keys->D.getY() && x <= keys->D.getY() + keys->D.getH())
return Down;
if (x >= keys->L.getX() && x <= (keys->L.getX() + keys->L.getW()) &&
y >= keys->L.getY() && x <= keys->L.getY() + keys->L.getH())
return Left;
if (x >= keys->R.getX() && x <= (keys->R.getX() + keys->R.getW()) &&
y >= keys->R.getY() && x <= keys->R.getY() + keys->R.getH())
return Right;
break;
}
default: break;
}
return None;
}
but when i debug my app on android the events act delayed despite they should have been returned and should be received before animation, so i guess if they are treated in another thread in Android or something because they act like independient to the animation.
Tried before with this:
float x = 0, y = 0, tmpx = 0, tmpy = 0;
while (SDL_PollEvent(&event)){
if (event.type == SDL_QUIT){ gameState = false; }
switch (event.type) {
case SDL_FINGERMOTION: {
tmpx = event.tfinger.dx;
tmpy = event.tfinger.dy;
window.get_AbsPixels(&tmpx, &tmpy);
x += tmpx; y += tmpy;
tmpx = tmpy = 0;
SDL_Log("\nDesplazamiento x: %f desplazamiento y: %f.\n", x, y);
break;
}
default: break;
}
if ((x > 70 || x < -70) || (y > 70 || y < -70))
return window.process_Dplcmnt(x, y);
}
return None;
..but it gave me also a lot of delays than the new one.
So to have it all clear and could act acording to, could someone explain me how the touch events should be processed using SDL on Android? Thanks in advance.
I already solve it, after every case:, even when no one fit on a condition there was always a returning so the pending events that didn't match kept there not flushing right, just moved the state return None; outside the while. Now it works like on PC.
float x = 0, y = 0;
while (SDL_PollEvent(&event)){
switch (event.type) {
case SDL_QUIT: { board->setGameState(false); break;}
case SDL_FINGERDOWN: {
x = event.tfinger.x;
y = event.tfinger.y;
SDL_Log("\nDesplazamiento x: %f desplazamiento y: %f.\n", x, y);
window.get_AbsPixels(&x, &y);
if (x > keys->U.getX() && x < (keys->U.getX() + keys->U.getW()) &&
y > keys->U.getY() && y < keys->U.getY() + keys->U.getH()) {
SDL_Log("\nRetornado Up\n");
return Up;
}
if (x > keys->D.getX() && x < (keys->D.getX() + keys->D.getW()) &&
y > keys->D.getY() && y < keys->D.getY() + keys->D.getH()) {
SDL_Log("\nRetornado Down\n");
return Down;
}
if (x > keys->L.getX() && x < (keys->L.getX() + keys->L.getW()) &&
y > keys->L.getY() && y < keys->L.getY() + keys->L.getH()) {
SDL_Log("\nRetornado Left\n");
return Left;
}
if (x > keys->R.getX() && x < (keys->R.getX() + keys->R.getW()) &&
y > keys->R.getY() && y < keys->R.getY() + keys->R.getH()) {
SDL_Log("\nRetornado Right\n");
return Right;
}
break;
}
default:
//SDL_PumpEvents();
//SDL_FlushEvent(SDL_FINGERDOWN);
break;
}
}
return None;
I'm trying to rotate a sprite based upon where my finger is placed on the touch screen.
I have an arrow and i want the arrow to be pointing at my finger at all times as i'm drag it around over the screen.
I could easily set the sprite to any rotation using sprite.setRotation(angle)
How should i go about this?
Much appreciated if you can point me in the right direction.
(ax, ay) is coordinates of the center of the arrow, and (fx, fy) is the coordinates of the finger, and a is the angle, here is some pseudocode:
dx = fx - ax
dy = fy - ay
if (dx == 0) {
a = 90
return
}
if (dy == 0) {
a = 0
return
}
//tan(a) == abs(dy) / abs(dx) therefore
a = arctan(dy / dx)
if (dx > 0 && dy > 0) {
// do nothing, a is correct
} else if (dx > 0 && dy < 0) {
a = 360 - a
} else if (dx < 0 && dy > 0) {
a = 180 - a
} else {
a = 180 + a
}
I didn't implement and test it yet, I'll do it later if there will be need
So, i am creating a joystic for a android game, so in my Touching class(implementing InputProcessor) it looks like a :
public class Touching implements InputProcessor{
int y = 0;
int x = 0;
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
x = Gdx.input.getX();
y = Gdx.input.getY();
if (x > 122 && x < 202 && y > 620 && y < 700 )
{
Core.player1.anmov(2); //button 1
}
if ( x > 122 && x < 202 && y > 520 && y < 600)
{
Core.player1.anmov(1); //button 2
}
if (x > 20 && x < 100 && y > 620 && y < 700)
{
Core.player1.anmov(3); //button 3
}
if (x > 222 && x < 302 && y > 620 && y < 700)
{
Core.player1.anmov(4); // button 4
}
return true;
}
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
x = Gdx.input.getX();
y = Gdx.input.getY();
if (x > 122 && x < 202 && y > 620 && y < 700)
{
Core.player1.anmov(7); // button 1
}
if ( x > 122 && x < 202 && y > 520 && y < 600)
{
Core.player1.anmov(8); // button 2
}
if (x > 20 && x < 100 && y > 620 && y < 700)
{
Core.player1.anmov(5); // button 3
}
if (x > 222 && x < 302 && y > 620 && y < 700)
{
Core.player1.anmov(6); // button 4
}
return false;
}
public boolean touchDragged(int screenX, int screenY, int pointer) {
x = Gdx.input.getX();
y = Gdx.input.getY();
return true;
}
so now, if i touch the button which represents moving on X, dragg to button which represents moving on Y, it is still moving on X, until i get my finger out of screen(the touchUP is calling), and then, it it standing, it does not move on Y..
Can anybody help me please? I think this is a very primitive, but i cant find a solution.
I would probably go for something like this in the player class update method itself
//Declare velocity on top so you just have to change this to fine tune speed.
float velocity = 10;
if (Gdx.input.isTouched()) //isTouched should register as long as a screen is touched, you can use pointers for multiple fingers.
{
if (touch within button) //just use Gdx.input.getX / Gdx.input.getY
{
position.X += velocity * Gdx.graphics.getDeltaTime();
{
//do for each button
}
Never used dragging for onscreen buttons myself but theoretically this should work since isTouched registers as long screen is touched. Gdx.input.getX/Y should update. You probably had something in there that only ran once and continued moving your player until a release was registered.
I've got this graph-like circle that is divided in several "portions". I draw these using drawArc on a canvas.
canvas.drawArc(oval, startAngle, sweepAngle, true, fillPaint);
I would like to make these arcs clickeable so I can trigger events when the user taps them. So I decided to override onTouchEvent, then for ACTION_DOWN go through all my portions and check if the touch position lies within them.
I tried this code here which is answering to a similar question, but I am getting strange angle values (i.e. negative values for top right quadrant, values between 180-270 in the rest of them).
public boolean isInArea(float x, float y){
int deltaX = (int) (x - oval.centerX());
int deltaY = (int) (y - oval.centerY());
if (Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2)) > mRectShape.width()/2) {
return false;
}
// offset for radiant, depending on quadrant
double offset = 0;
if (deltaX > 0 && deltaY < 0) {
// top right -> nothing to do
} else if (deltaX > 0 && deltaY > 0) {
// bottom right -> add 90 degrees
offset = Math.PI/2;
} else if (deltaX < 0 && deltaY > 0) {
// bottom left -> add 180 degrees
offset = Math.PI;
} else if (deltaX < 0 && deltaY < 0) {
// top left -> add 270 degrees
offset = Math.PI * 3/2;
}
//now calculate angle
double angle = Math.asin(deltaY / deltaX);
double total = angle + offset;
double totalDeg = total * 180 / Math.PI;
Log.d(LOG_TAG, "angle :" + totalDeg);
if(totalDeg > mStartAngle && totalDeg < mSweepAngle){
return true;
}
return false;
}
I also tried without setting the offsets nand then I get negative values for top quadrants, and positive values between 0 and 180 in the bottom ones.
Also tried using atan2 like this:
angle = Math.atan2(deltaY, -deltaX);
What am I missing here?