Move Ball around screen. Accelerometer. Bounce too - android

I have to do an app in Android that moves a ball around the screen. I need to move the ball with the accelerometer.
I have this code but the ball go around the border and doesn't bounce.
package com.example.test2;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.drawable.ShapeDrawable;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.Display;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
public class test2 extends Activity implements SensorEventListener {
CustomDrawableView mCustomDrawableView = null;
ShapeDrawable mDrawable = new ShapeDrawable();
public float xPosition, xAcceleration, xVelocity = 0.0f;
public float yPosition, yAcceleration, yVelocity = 0.0f;
public float xmax, ymax;
private Bitmap mBitmap;
private Bitmap mWood;
private SensorManager sensorManager = null;
public float frameTime = 0.666f;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set FullScreen & portrait
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
// Get a reference to a SensorManager
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
SensorManager.SENSOR_DELAY_GAME);
mCustomDrawableView = new CustomDrawableView(this);
setContentView(mCustomDrawableView);
// setContentView(R.layout.main);
// Calculate Boundry
Display display = getWindowManager().getDefaultDisplay();
xmax = (float) display.getWidth() - 50;
ymax = (float) display.getHeight() - 50;
}
// This method will update the UI on new sensor events
public void onSensorChanged(SensorEvent sensorEvent) {
{
if (sensorEvent.sensor.getType() == Sensor.TYPE_ORIENTATION) {
// Set sensor values as acceleration
yAcceleration = sensorEvent.values[1];
xAcceleration = sensorEvent.values[2];
updateBall();
}
}
}
private void updateBall() {
// Calculate new speed
xVelocity += (xAcceleration * frameTime);
yVelocity += (yAcceleration * frameTime);
// Calc distance travelled in that time
float xS = (xVelocity / 2) * frameTime;
float yS = (yVelocity / 2) * frameTime;
// Add to position negative due to sensor
// readings being opposite to what we want!
xPosition -= xS;
yPosition -= yS;
if (xPosition > xmax) {
xPosition = xmax;
} else if (xPosition < 0) {
xPosition = 0;
}
if (yPosition > ymax) {
yPosition = ymax;
} else if (yPosition < 0) {
yPosition = 0;
}
}
// I've chosen to not implement this method
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub
}
#Override
protected void onResume() {
super.onResume();
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
SensorManager.SENSOR_DELAY_GAME);
}
#Override
protected void onStop() {
// Unregister the listener
sensorManager.unregisterListener(this);
super.onStop();
}
public class CustomDrawableView extends View {
public CustomDrawableView(Context context) {
super(context);
Bitmap ball = BitmapFactory.decodeResource(getResources(),
R.drawable.ball);
final int dstWidth = 50;
final int dstHeight = 50;
mBitmap = Bitmap
.createScaledBitmap(ball, dstWidth, dstHeight, true);
mWood = BitmapFactory.decodeResource(getResources(),
R.drawable.wood);
}
protected void onDraw(Canvas canvas) {
final Bitmap bitmap = mBitmap;
canvas.drawBitmap(mWood, 0, 0, null);
canvas.drawBitmap(bitmap, xPosition, yPosition, null);
invalidate();
}
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
// TODO Auto-generated method stub
super.onConfigurationChanged(newConfig);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}
How can I solve it?
Thank you

You want to move it with the accelerometer, but you're registering an orientation sensor listener. Register for the accelerometer instead.

Related

Get a ball to roll around inside another circle

I'm trying to get a ball to bounce and roll around inside another ball, ultimately based on the accelerometer. There are countless tutorials out there to detect circle collisions and such, and they are indeed marginally helpful. Unfortunately, none that I have found deal with circle-inside-of-a-circle collision only circles bouncing around in a rectangle view.
Several helpful URLs are, where I got most of this code:
http://xiangchen.wordpress.com/2011/12/17/an-android-accelerometer-example/
circle-circle collision
..but again, this isn't quite what I'm after.
I want to get a circle to bounce and roll around inside of another circle. Then, after that, I will want the inner ball to roll down the inside of the outer circle at the right time as the velocity lessens, not simply bounce to the bottom. Am I articulating that clearly? And finally, the bounce angle will need to be adjusted I'm sure so I will ultimately need to figure out how to do that as well.
My code is a mess because I've tried so many things, so in particular, the commented block isn't even close to what it needs to be I don't think. It is just my latest attempt.
Anyone know a little something about this and willing to give me a hand? I would appreciate it.
Edit: This guy is very close to what I'm after, but I am having trouble making sense of it and converting the selected answer into Java. Help? https://gamedev.stackexchange.com/questions/29650/circle-inside-circle-collision
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.RectF;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class Main extends Activity implements SensorEventListener {
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private ShapeView mShapeView;
private int mWidthScreen;
private int mHeightScreen;
private final float FACTOR_FRICTION = 0.2f; // imaginary friction on the screen
private final float GRAVITY = 9.8f; // acceleration of gravity
private float mAx; // acceleration along x axis
private float mAy; // acceleration along y axis
private final float mDeltaT = 0.5f; // imaginary time interval between each acceleration updates
private static final float OUTERSTROKE = 5;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
mWidthScreen = displaymetrics.widthPixels;
mHeightScreen = displaymetrics.heightPixels;
mShapeView = new ShapeView(this);
mShapeView.initOvalCenter((int) (mWidthScreen * 0.6), (int) (mHeightScreen * 0.6));
setContentView(mShapeView);
}
#Override
public void onSensorChanged(SensorEvent event) {
// obtain the three accelerations from sensors
mAx = event.values[0];
mAy = event.values[1];
float mAz = event.values[2];
// taking into account the frictions
mAx = Math.signum(mAx) * Math.abs(mAx) * (1 - FACTOR_FRICTION * Math.abs(mAz) / GRAVITY);
mAy = Math.signum(mAy) * Math.abs(mAy) * (1 - FACTOR_FRICTION * Math.abs(mAz) / GRAVITY);
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
#Override
protected void onResume() {
super.onResume();
// start sensor sensing
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
protected void onPause() {
super.onPause();
// stop sensor sensing
mSensorManager.unregisterListener(this);
}
// the view that renders the ball
private class ShapeView extends SurfaceView implements SurfaceHolder.Callback {
private final int BALLRADIUS = 100;
private final float FACTOR_BOUNCEBACK = 0.15f;
private final int OUTERRADIUS = 300;
private Point ballCenter = new Point();
private RectF mRectF;
private final Paint mPaint;
private ShapeThread mThread;
private float mVx;
private float mVy;
private final Paint outerPaint;
private RectF outerBounds;
private Point outerCenter;
private final double outerDiagonal;
public ShapeView(Context context) {
super(context);
getHolder().addCallback(this);
mThread = new ShapeThread(getHolder(), this);
setFocusable(true);
mPaint = new Paint();
mPaint.setColor(0xFFFFFFFF);
mPaint.setAlpha(192);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setAntiAlias(true);
outerPaint= new Paint();
outerPaint.setColor(0xFFFFFFFF);
outerPaint.setAlpha(255);
outerPaint.setStrokeWidth(OUTERSTROKE);
outerPaint.setStyle(Paint.Style.STROKE);
outerPaint.setAntiAlias(true);
mRectF = new RectF();
outerDiagonal= Math.pow(BALLRADIUS - OUTERRADIUS, 2);
}
public void initOvalCenter(int x, int y) {
mShapeView.setOvalCenter(x, y);
outerCenter= new Point(x, y);
outerBounds = new RectF(x - OUTERRADIUS, y - OUTERRADIUS, x + OUTERRADIUS, y + OUTERRADIUS);
}
public boolean setOvalCenter(int x, int y) {
ballCenter.set(x, y);
return true;
}
public boolean updateOvalCenter() {
/*-------
* This is where the trouble is, currently. How do I "snap" the inner circle back into the
* outer circle? Or even better, how do I keep it from crossing the line to bring with?
*/
mVx -= mAx * mDeltaT;
mVy += mAy * mDeltaT;
Point newBallCenter = new Point();
newBallCenter.x = ballCenter.x + (int) (mDeltaT * (mVx + 0.5 * mAx * mDeltaT));
newBallCenter.y = ballCenter.y + (int) (mDeltaT * (mVy + 0.5 * mAy * mDeltaT));
double distance = Math.sqrt(Math.pow(newBallCenter.x - outerCenter.x, 2) + Math.pow(newBallCenter.y - outerCenter.y, 2));
if(distance >= OUTERRADIUS - BALLRADIUS) {
mVx = -mVx * FACTOR_BOUNCEBACK;
mVy = -mVy * FACTOR_BOUNCEBACK;
newBallCenter.x = ballCenter.x + (int) (mDeltaT * (mVx + 0.5 * mAx * mDeltaT));
newBallCenter.y = ballCenter.y + (int) (mDeltaT * (mVy + 0.5 * mAy * mDeltaT));
}
ballCenter.x = newBallCenter.x;
ballCenter.y = newBallCenter.y;
return true;
}
protected void doDraw(Canvas canvas) {
if (mRectF != null && canvas != null) {
mRectF.set(ballCenter.x - BALLRADIUS, ballCenter.y - BALLRADIUS, ballCenter.x + BALLRADIUS, ballCenter.y + BALLRADIUS);
canvas.drawColor(0XFF000000);
canvas.drawOval(mRectF, mPaint);
canvas.drawOval(outerBounds, outerPaint);
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
mThread.setRunning(true);
mThread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
mThread.setRunning(false);
while (retry) {
try {
mThread.join();
retry = false;
} catch (InterruptedException ignored) { }
}
}
}
class ShapeThread extends Thread {
private final SurfaceHolder mSurfaceHolder;
private ShapeView mShapeView;
private boolean mRun = false;
public ShapeThread(SurfaceHolder surfaceHolder, ShapeView shapeView) {
mSurfaceHolder = surfaceHolder;
mShapeView = shapeView;
}
public void setRunning(boolean run) {
mRun = run;
}
#Override
public void run() {
Canvas c;
while (mRun) {
mShapeView.updateOvalCenter();
c = null;
try {
c = mSurfaceHolder.lockCanvas(null);
synchronized (mSurfaceHolder) {
mShapeView.doDraw(c);
}
} finally {
if (c != null) {
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
}
I thought i would answer this to at least help you even if it doesnt answer your question completely.
Below is your code with changes to a few things
i fixed your issue with snapping the inner circle back when a collision occurs.
Basically you need to move the inner circle back by one frame once a collision has occured. i think you tried doing this however you were resetting these values just before the collision check. I also added a little check to the velocity to say if it was less than 0.5 then just move the inner circle to the last frame without a bounce to get rid of the judering bouncing effect when it is trying to settle.
package com.test.circleincircle;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.RectF;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class Main extends Activity implements SensorEventListener {
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private ShapeView mShapeView;
private int mWidthScreen;
private int mHeightScreen;
private final float FACTOR_FRICTION = 0.2f; // imaginary friction on the screen
private final float GRAVITY = 9.8f; // acceleration of gravity
private float mAx; // acceleration along x axis
private float mAy; // acceleration along y axis
private final float mDeltaT = 0.5f; // imaginary time interval between each acceleration updates
private int previousInnerX, previousInnerY;
private static final float OUTERSTROKE = 5;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
mWidthScreen = displaymetrics.widthPixels;
mHeightScreen = displaymetrics.heightPixels;
mShapeView = new ShapeView(this);
mShapeView.initOvalCenter((int) (mWidthScreen * 0.6), (int) (mHeightScreen * 0.6));
setContentView(mShapeView);
}
#Override
public void onSensorChanged(SensorEvent event) {
// obtain the three accelerations from sensors
mAx = event.values[0];
mAy = event.values[1];
float mAz = event.values[2];
// taking into account the frictions
mAx = Math.signum(mAx) * Math.abs(mAx) * (1 - FACTOR_FRICTION * Math.abs(mAz) / GRAVITY);
mAy = Math.signum(mAy) * Math.abs(mAy) * (1 - FACTOR_FRICTION * Math.abs(mAz) / GRAVITY);
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
#Override
protected void onResume() {
super.onResume();
// start sensor sensing
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
protected void onPause() {
super.onPause();
// stop sensor sensing
mSensorManager.unregisterListener(this);
}
// the view that renders the ball
private class ShapeView extends SurfaceView implements SurfaceHolder.Callback {
private final int BALLRADIUS = 100;
private final float FACTOR_BOUNCEBACK = 0.45f;
private final int OUTERRADIUS = 300;
private Point ballCenter = new Point();
private RectF mRectF;
private final Paint mPaint;
private ShapeThread mThread;
private float mVx;
private float mVy;
private final Paint outerPaint;
private RectF outerBounds;
private Point outerCenter;
private final double outerDiagonal;
public ShapeView(Context context) {
super(context);
getHolder().addCallback(this);
mThread = new ShapeThread(getHolder(), this);
setFocusable(true);
mPaint = new Paint();
mPaint.setColor(0xFFFFFFFF);
mPaint.setAlpha(192);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setAntiAlias(true);
outerPaint= new Paint();
outerPaint.setColor(0xFFFFFFFF);
outerPaint.setAlpha(255);
outerPaint.setStrokeWidth(OUTERSTROKE);
outerPaint.setStyle(Paint.Style.STROKE);
outerPaint.setAntiAlias(true);
mRectF = new RectF();
outerDiagonal= Math.pow(BALLRADIUS - OUTERRADIUS, 2);
}
public void initOvalCenter(int x, int y) {
mShapeView.setOvalCenter(x, y);
outerCenter= new Point(x, y);
outerBounds = new RectF(x - OUTERRADIUS, y - OUTERRADIUS, x + OUTERRADIUS, y + OUTERRADIUS);
}
public boolean setOvalCenter(int x, int y) {
ballCenter.set(x, y);
return true;
}
public boolean updateOvalCenter() {
Point newBallCenter = new Point();
newBallCenter.x = ballCenter.x + (int) (mDeltaT * (mVx + 0.5 * mAx * mDeltaT));
newBallCenter.y = ballCenter.y + (int) (mDeltaT * (mVy + 0.5 * mAy * mDeltaT));
double distance = Math.sqrt(Math.pow(newBallCenter.x - outerCenter.x, 2) + Math.pow(newBallCenter.y - outerCenter.y, 2));
if(distance >= OUTERRADIUS - BALLRADIUS) {
mVx = -mVx * FACTOR_BOUNCEBACK;
mVy = -mVy * FACTOR_BOUNCEBACK;
if(Math.abs(mVx) > 0.5)
{
newBallCenter.x = previousInnerX + (int) (mDeltaT * (mVx + 0.5 * mAx * mDeltaT));
newBallCenter.y = previousInnerY + (int) (mDeltaT * (mVy + 0.5 * mAy * mDeltaT));
}
else
{
newBallCenter.x = previousInnerX;
newBallCenter.y = previousInnerY;
}
}
else
{
mVx -= mAx * mDeltaT;
mVy += mAy * mDeltaT;
}
previousInnerX = ballCenter.x;
previousInnerY = ballCenter.y;
ballCenter.x = newBallCenter.x;
ballCenter.y = newBallCenter.y;
return true;
}
protected void doDraw(Canvas canvas) {
if (mRectF != null && canvas != null) {
mRectF.set(ballCenter.x - BALLRADIUS, ballCenter.y - BALLRADIUS, ballCenter.x + BALLRADIUS, ballCenter.y + BALLRADIUS);
canvas.drawColor(0XFF000000);
canvas.drawOval(mRectF, mPaint);
canvas.drawOval(outerBounds, outerPaint);
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
mThread.setRunning(true);
mThread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
mThread.setRunning(false);
while (retry) {
try {
mThread.join();
retry = false;
} catch (InterruptedException ignored) { }
}
}
}
class ShapeThread extends Thread {
private final SurfaceHolder mSurfaceHolder;
private ShapeView mShapeView;
private boolean mRun = false;
public ShapeThread(SurfaceHolder surfaceHolder, ShapeView shapeView) {
mSurfaceHolder = surfaceHolder;
mShapeView = shapeView;
}
public void setRunning(boolean run) {
mRun = run;
}
#Override
public void run() {
Canvas c;
while (mRun) {
mShapeView.updateOvalCenter();
c = null;
try {
c = mSurfaceHolder.lockCanvas(null);
synchronized (mSurfaceHolder) {
mShapeView.doDraw(c);
}
} finally {
if (c != null) {
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
}
Adding in the smooth movement of the iner circle rolling within the outer one while also bouncing will be a lot more difficult to implement. The correct way would be to have the inner circle rotating and following the instructions from the question you reference.
Maybe you can ask a seperate question for that part after you are happy with the bouncing.
If anything this may just help you along your journey and hopefully you will be able to add to this.

How to make my app intent to an other screen when something happens

Well, I have an app with a ball, moving using the accelerometer sensor, now, I want it to intent me to the screen "GameOver.java" when the ball is touching the corners (top,bottom,left and right of the screen).
Here is my code :
package com.example.theball;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.Menu;
import android.widget.ImageView;
#SuppressWarnings("deprecation") public class MainActivity extends Activity implements SensorEventListener {
private SensorManager sensorManager;
private Sensor accelerometer;
private long lastUpdate;
AnimatedView animatedView = null;
ShapeDrawable mDrawable = new ShapeDrawable();
public static int x;
public static int y;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
accelerometer = sensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
lastUpdate = System.currentTimeMillis();
animatedView = new AnimatedView(this);
setContentView(animatedView);
}
#Override
protected void onResume() {
super.onResume();
sensorManager.registerListener(this, accelerometer,
SensorManager.SENSOR_DELAY_GAME);
}
#Override
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
}
#Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub
}
#Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
x -= (int) event.values[0];
y += (int) event.values[1];
}
}
public class AnimatedView extends ImageView {
static final int width = 50;
static final int height = 50;
public AnimatedView(Context context) {
super(context);
// TODO Auto-generated constructor stub
mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(0xffffAC23);
mDrawable.setBounds(x, y, x + width, y + height);
}
#Override
protected void onDraw(Canvas canvas) {
mDrawable.setBounds(x, y, x + width, y + height);
mDrawable.draw(canvas);
invalidate();
}
}
}
Assuming I understand your question correctly:
Every time the ball moves -- in your onSensorChanged(..) method -- you need to check if x == upper x bound or lower x bound and if y == upper y bound or lower y bound... If any of these conditions resolves to true that means the center of the ball is touching an edge and GameOver.java should be started:
EDIT:
// where 0 is the lower bound and 50 is the upper bound of our canvas
if(x <= 0 || x >= 50 || y <= 0 || y >= 50) {
Intent myIntent = new Intent(this, GameOver.class);
startActivity(myIntent);
}

Adding animatedView to existing layout

Ok, so here is my full code:
package com.example.theball;
import java.util.Timer;
import java.util.TimerTask;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.ActivityInfo;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.Display;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
#SuppressLint("NewApi")
#SuppressWarnings("unused")
public class MainActivity extends Activity implements SensorEventListener {
private SensorManager sensorManager;
private Sensor accelerometer;
private long lastUpdate;
AnimatedView animatedView = null;
ShapeDrawable mDrawable = new ShapeDrawable();
public static int x;
public static int y;
public static final int width = 50;
public static final int height = 50;
public boolean firstDraw = true;
private int screen_width;
private int screen_height;
private int sensorX;
private Timer t;
private int TimeCounter = 0;
private TextView highscore_int;
private int sensorY;
#SuppressWarnings("deprecation")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
highscore_int = (TextView) findViewById(R.id.highscore_int);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
accelerometer = sensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
lastUpdate = System.currentTimeMillis();
animatedView = new AnimatedView(this);
setContentView(animatedView);
t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
public void run() {
runOnUiThread(new Runnable() {
public void run() {
TimeCounter++;
}
});
}
}, 0, 1000);
}
#Override
protected void onResume() {
super.onResume();
sensorManager.registerListener(this, accelerometer,
SensorManager.SENSOR_DELAY_GAME);
}
#Override
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
}
#Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub
}
#Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
sensorY = (int) event.values[1];
sensorX = (int) event.values[0];
x -= sensorX * 3;
y += sensorY * 3;
if (x <= 0 || x >= screen_width || y <= 0 || y >= screen_height) {
finish();
Intent myIntent = new Intent(this, YouLost.class);
startActivity(myIntent);
}
}
}
public class AnimatedView extends ImageView {
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
static final int width = 50;
static final int height = 50;
#SuppressLint("NewApi")
public AnimatedView(Context context) {
super(context);
// TODO Auto-generated constructor stub
display.getSize(size);
screen_width = size.x;
screen_height = size.y;
mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(0xffffAC23);
mDrawable.setBounds(0, 0, screen_width, screen_height);
}
#Override
protected void onDraw(Canvas canvas) {
mDrawable.setBounds(x, y, x + width, y + height);
if (firstDraw) {
x = screen_width / 2;
y = screen_height / 2;
firstDraw = false;
}
mDrawable.draw(canvas);
invalidate();
}
}
}
My problem is, I want to use the activity_main layout and still have the animatedView, How can I do it? Please, don't say my problem is I set twice the setContentView, I KNOW I DID IT! That's because I want a ball and a layout.
Here someone else with my problem:http://stackoverflow.com/questions/22580336/android-animatedview-taking-up-whole-activity-screen .
The animatedView creating an empty layout for himself, if I will delete the "setContentView(animatedView)" I will have my layout but not my ball.
Now I have an empty layout with a ball.
Can you please post your XML for activity_main?
It sounds like what you want to do is create a FrameLayout as the top-level view in your activity layout. This will allow you to stack child views on top of one another. Then, after your call to setContentView(R.layout.activity_main), you can do something like this:
FrameLayout myRootLayout = (FrameLayout) findViewById(R.id.id_of_top_level_framelayout);
animatedView = new AnimatedView(this);
myRootLayout.addView(animatedView);
Alternately you can use addView(animatedView, index) if you want to specify the z-order of the animatedView.
Please clarify if I misunderstood your question.

Is it possible to have more than one setContentView in one class?

I am trying to print the rectangle shape and the main xml aswell as I want the shape and the figures, is this possible? If not how can I print a shape from java code and my main xml both on to my emulator? Thank you
package com.example.accel;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RectShape;
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.TextView;
public class AccelActivity extends Activity implements SensorEventListener
{
/** Called when the activity is first created. */
CustomDrawableView mCustomDrawableView = null;
ShapeDrawable mDrawable = new ShapeDrawable();
public static int x;
public static int y;
public static int z;
private SensorManager sensorManager = null;
TextView x1, y1, z1;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Get a reference to a SensorManager
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mCustomDrawableView = new CustomDrawableView(this);
setContentView(mCustomDrawableView);
setContentView(R.layout.main);
}
// This method will update the UI on new sensor events
public void onSensorChanged(SensorEvent sensorEvent)
{
{
if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
TextView tvX= (TextView)findViewById(R.id.x_axis);
TextView tvY= (TextView)findViewById(R.id.y_axis);
TextView tvZ= (TextView)findViewById(R.id.z_axis);
x = (int) Math.pow(sensorEvent.values[0], 2);
y = (int) Math.pow(sensorEvent.values[1], 2);
z = (int) Math.pow(sensorEvent.values[2], 2);
}
// if (sensorEvent.sensor.getType() == Sensor.TYPE_ORIENTATION) {
// }
}
}
// I've chosen to not implement this method
public void onAccuracyChanged(Sensor arg0, int arg1)
{
// TODO Auto-generated method stub
}
#Override
protected void onResume()
{
super.onResume();
// Register this class as a listener for the accelerometer sensor
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_FASTEST);
// ...and the orientation sensor
}
#Override
protected void onStop()
{
// Unregister the listener
sensorManager.unregisterListener(this);
super.onStop();
}
public class CustomDrawableView extends View
{
static final int width = 150;
static final int height = 250;
public CustomDrawableView(Context context)
{
super(context);
mDrawable = new ShapeDrawable(new RectShape());
mDrawable.getPaint().setColor(0xff74AC23);
mDrawable.setBounds(x, y, x + width, y + height);
}
protected void onDraw(Canvas canvas)
{
RectF rect = new RectF(AccelActivity.x, AccelActivity.y, AccelActivity.x + width, AccelActivity.y
+ height); // set bounds of rectangle
Paint p = new Paint(); // set some paint options
p.setColor(Color.BLUE);
canvas.drawRect(rect, p);
invalidate();
}
}
}
yes, you can.
setcontentview(anotherLayout), so you pring the new layout in your activity.
or you can define other elements in your mainLayout and you manipulate it by the function setVisibily
if you need elementA:
elementA = findViewById(R.id.elementA);
elementA.setVisibility(true);
and if you don't need it:
elementA.setVisibility(false);

Moving an image using Accelerometer of android

I have read articles/tutorial about accessing the phone's accelerometer (acceleration and orientation) values. I am trying to build a simple app where I can move a ball image using the these values. Here is my code:
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
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.TextView;
public class Accelerometer extends Activity implements SensorEventListener {
/** Called when the activity is first created. */
CustomDrawableView mCustomDrawableView = null;
ShapeDrawable mDrawable = new ShapeDrawable();
int x ;
int y ;
private SensorManager sensorManager = null;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get a reference to a SensorManager
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mCustomDrawableView = new CustomDrawableView(this);
setContentView(mCustomDrawableView);
// setContentView(R.layout.main);
}
// This method will update the UI on new sensor events
public void onSensorChanged(SensorEvent sensorEvent) {
{
if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
int someNumber = 100;
float xChange = someNumber * sensorEvent.values[1];
//values[2] can be -90 to 90
float yChange = someNumber * 2 * sensorEvent.values[2];
x = x + (int)xChange;
y = y + (int)yChange;
}
if (sensorEvent.sensor.getType() == Sensor.TYPE_ORIENTATION) {
}
}
}
// I've chosen to not implement this method
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub
}
#Override
protected void onResume() {
super.onResume();
// Register this class as a listener for the accelerometer sensor
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
// ...and the orientation sensor
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION), SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
protected void onStop() {
// Unregister the listener
sensorManager.unregisterListener(this);
super.onStop();
}
public class CustomDrawableView extends View {
public CustomDrawableView(Context context) {
super(context);
int width = 50;
int height = 50;
mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(0xff74AC23);
mDrawable.setBounds(x, y, x + width, y + height);
}
protected void onDraw(Canvas canvas) {
mDrawable.draw(canvas);
invalidate();
}
}
}
I am getting an oval shape displayed on the screen but nothing happens after that.
thanks
Use this code. You were never setting the location of the drawable after you intialized that class. You'll have to do some calculations to set the balls location properly. The way you were doing it was getting values over 10000 which was drawing the oval off screen.
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.View;
public class Accelerometer extends Activity implements SensorEventListener
{
/** Called when the activity is first created. */
CustomDrawableView mCustomDrawableView = null;
ShapeDrawable mDrawable = new ShapeDrawable();
public static int x;
public static int y;
private SensorManager sensorManager = null;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Get a reference to a SensorManager
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mCustomDrawableView = new CustomDrawableView(this);
setContentView(mCustomDrawableView);
// setContentView(R.layout.main);
}
// This method will update the UI on new sensor events
public void onSensorChanged(SensorEvent sensorEvent)
{
{
if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
// the values you were calculating originally here were over 10000!
x = (int) Math.pow(sensorEvent.values[1], 2);
y = (int) Math.pow(sensorEvent.values[2], 2);
}
if (sensorEvent.sensor.getType() == Sensor.TYPE_ORIENTATION) {
}
}
}
// I've chosen to not implement this method
public void onAccuracyChanged(Sensor arg0, int arg1)
{
// TODO Auto-generated method stub
}
#Override
protected void onResume()
{
super.onResume();
// Register this class as a listener for the accelerometer sensor
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL);
// ...and the orientation sensor
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
protected void onStop()
{
// Unregister the listener
sensorManager.unregisterListener(this);
super.onStop();
}
public class CustomDrawableView extends View
{
static final int width = 50;
static final int height = 50;
public CustomDrawableView(Context context)
{
super(context);
mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(0xff74AC23);
mDrawable.setBounds(x, y, x + width, y + height);
}
protected void onDraw(Canvas canvas)
{
RectF oval = new RectF(Accelerometer.x, Accelerometer.y, Accelerometer.x + width, Accelerometer.y
+ height); // set bounds of rectangle
Paint p = new Paint(); // set some paint options
p.setColor(Color.BLUE);
canvas.drawOval(oval, p);
invalidate();
}
}
}
Here is my implementation of this problem. Dymmeh's solution kept throwing problems at me, so I refactored it until I got it working.
package edu.ian495.accelerometertest;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.Menu;
import android.widget.ImageView;
public class MainActivity extends Activity implements SensorEventListener {
private SensorManager sensorManager;
private Sensor accelerometer;
private long lastUpdate;
AnimatedView animatedView = null;
ShapeDrawable mDrawable = new ShapeDrawable();
public static int x;
public static int y;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
accelerometer = sensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
lastUpdate = System.currentTimeMillis();
animatedView = new AnimatedView(this);
setContentView(animatedView);
}
#Override
protected void onResume() {
super.onResume();
sensorManager.registerListener(this, accelerometer,
SensorManager.SENSOR_DELAY_GAME);
}
#Override
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
#Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub
}
#Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
x -= (int) event.values[0];
y += (int) event.values[1];
}
}
public class AnimatedView extends ImageView {
static final int width = 50;
static final int height = 50;
public AnimatedView(Context context) {
super(context);
// TODO Auto-generated constructor stub
mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(0xffffAC23);
mDrawable.setBounds(x, y, x + width, y + height);
}
#Override
protected void onDraw(Canvas canvas) {
mDrawable.setBounds(x, y, x + width, y + height);
mDrawable.draw(canvas);
invalidate();
}
}
}
I have done some changes in onSensorChange code to move the ball in the screen. With the example in my case the ball donĀ“t move correctly and for that I did the changes. This example Works fine for my.
public void onSensorChanged(SensorEvent sensorEvent)
{
//Try synchronize the events
synchronized(this){
//For each sensor
switch (sensorEvent.sensor.getType()) {
case Sensor.TYPE_MAGNETIC_FIELD: //Magnetic sensor to know when the screen is landscape or portrait
//Save values to calculate the orientation
mMagneticValues = sensorEvent.values.clone();
break;
case Sensor.TYPE_ACCELEROMETER://Accelerometer to move the ball
if (bOrientacion==true){//Landscape
//Positive values to move on x
if (sensorEvent.values[1]>0){
//In margenMax I save the margin of the screen this value depends of the screen where we run the application. With this the ball not disapears of the screen
if (x<=margenMaxX){
//We plus in x to move the ball
x = x + (int) Math.pow(sensorEvent.values[1], 2);
}
}
else{
//Move the ball to the other side
if (x>=margenMinX){
x = x - (int) Math.pow(sensorEvent.values[1], 2);
}
}
//Same in y
if (sensorEvent.values[0]>0){
if (y<=margenMaxY){
y = y + (int) Math.pow(sensorEvent.values[0], 2);
}
}
else{
if (y>=margenMinY){
y = y - (int) Math.pow(sensorEvent.values[0], 2);
}
}
}
else{//Portrait
//Eje X
if (sensorEvent.values[0]<0){
if (x<=margenMaxX){
x = x + (int) Math.pow(sensorEvent.values[0], 2);
}
}
else{
if (x>=margenMinX){
x = x - (int) Math.pow(sensorEvent.values[0], 2);
}
}
//Eje Y
if (sensorEvent.values[1]>0){
if (y<=margenMaxY){
y = y + (int) Math.pow(sensorEvent.values[1], 2);
}
}
else{
if (y>=margenMinY){
y = y - (int) Math.pow(sensorEvent.values[1], 2);
}
}
}
//Save the values to calculate the orientation
mAccelerometerValues = sensorEvent.values.clone();
break;
case Sensor.TYPE_ROTATION_VECTOR: //Rotation sensor
//With this value I do the ball bigger or smaller
if (sensorEvent.values[1]>0){
z=z+ (int) Math.pow(sensorEvent.values[1]+1, 2);
}
else{
z=z- (int) Math.pow(sensorEvent.values[1]+1, 2);
}
default:
break;
}
//Screen Orientation
if (mMagneticValues != null && mAccelerometerValues != null) {
float[] R = new float[16];
SensorManager.getRotationMatrix(R, null, mAccelerometerValues, mMagneticValues);
float[] orientation = new float[3];
SensorManager.getOrientation(R, orientation);
//if x have positives values the screen orientation is landscape in other case is portrait
if (orientation[0]>0){//LandScape
//Here I change the margins of the screen for the ball not disapear
bOrientacion=true;
margenMaxX=1200;
margenMinX=0;
margenMaxY=500;
margenMinY=0;
}
else{//Portrait
bOrientacion=false;
margenMaxX=600;
margenMinX=0;
margenMaxY=1000;
margenMinY=0;
}
}
}
}
The view class where I draw the ball
public class CustomDrawableView extends View
{
static final int width = 50;
static final int height = 50;
//Constructor de la figura
public CustomDrawableView(Context context)
{
super(context);
mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(0xff74AC23);
mDrawable.setBounds(x, y, x + width, y + height);
}
//Dibujamos la figura
protected void onDraw(Canvas canvas)
{
//Actividad_Principal x,y,z are variables from the main activity where I have the onSensorChange
RectF oval = new RectF(Actividad_Principal.x+Actividad_Principal.z, Actividad_Principal.y+Actividad_Principal.z, Actividad_Principal.x + width, Actividad_Principal.y + height);
Paint p = new Paint();
p.setColor(Color.BLUE);
canvas.drawOval(oval, p);
invalidate();
}
}
}
That is all, I hope help us.
Try using sensorEvent.values[0] for your xChange and sensorEvents.values[1] for your yChange if you want to use the acceleration sensor, if not use the same values and move it into the (sensorEvent.sensor.getType() == Sensor.TYPE_ORIENTATION) if statement, this will give you the tilt of the handset rather than how quickly its moving along an axis.
You also need to call invalidate(); on the View when you set or change a sensor.
The Sensor.TYPE_ACCELEROMETER returns:
values[0]: Acceleration minus Gx on the x-axis
values[1]: Acceleration minus Gy on the y-axis
values[2]: Acceleration minus Gz on the z-axis
The Sensor.TYPE_ORIENTATION returns:
values[0]: Azimuth, angle between the magnetic north direction and the y-axis, around the z-axis (0 to 359). 0=North, 90=East, 180=South, 270=West
values[1]: Pitch, rotation around x-axis (-180 to 180), with positive values when the z-axis moves toward the y-axis.
values[2]: Roll, rotation around y-axis (-90 to 90), with positive values when the x-axis moves toward the z-axis.
use the following library instead scrolling motion
add this line in top XML view
xmlns:parallax="http://schemas.android.com/apk/res-auto"
for Layout
<com.nvanbenschoten.motion.ParallaxImageView
android:id="#+id/parallex"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/image_hd"
parallax:motionTiltSensitivity="2.5" />
for code in your onCreate() method
ParallaxImageView mBackground = (ParallaxImageView) findViewById(R.id.parallex);
in your onResume() method
if(mBackground!=null)
mBackground.registerSensorManager();
in your onDestroy() method
// Unregister SensorManager when exiting
mBackground.unregisterSensorManager();
I think you need to invalidate your view in the onSensorChanged() method or at a specific fps rate that you have to implement.

Categories

Resources