moving an object in a circle - android - java

I posted this question yesterday, I got some useful help but was unable to solve the problem. Just figured I'd keep trying.
Ok. I'm trying to make a ball move in a circle on a canvas in Android. After doing some research and reading a few similar questions - I think I got the logic down but the shape remains stationary. Basically I'm doing x = a +rcos(theta), y = rain(theta). I'm not really sure what the problem is. My code is below. Does anyone know what I'm doing wrong? I've read the other questions and don't know why I can't make it work.
public class DrawingTheBall extends View {
Bitmap bball;
int x,y, theta;
public DrawingTheBall(Context context) {
super(context);
// TODO Auto-generated constructor stub
bball = BitmapFactory.decodeResource(getResources(), R.drawable.blueball);
x = 0;
y = 0;
theta = 45;
}
public void onDraw(Canvas canvas){
super.onDraw(canvas);
Rect ourRect = new Rect();
ourRect.set(0, 0, canvas.getWidth(), canvas.getHeight()/2);
float a = 10;
float b = 10;
float r = 20;
theta = (int) Math.toRadians(10);
Paint blue = new Paint();
blue.setColor(Color.BLUE);
blue.setStyle(Paint.Style.FILL);
canvas.drawRect(ourRect, blue);
if(x < canvas.getWidth()){
x = (int) (a +r*Math.cos(theta));
}else{
x = 0;
}
if(y < canvas.getHeight()){
y = (int) (b +r*Math.sin(theta));
}else{
y = 0;
}
Paint p = new Paint();
canvas.drawBitmap(bball, x, y, p);
invalidate();
}
}

You have to increment theta on the line:
theta = (int) Math.toRadians(10);
If you always draw at the same angle, you'll always draw to the same location.
EDIT:
You could place the above line in your constructor, and then in onDraw, you could do:
theta = (theta + 0.1) % (2 * Math.PI)

Related

Drawing a graph in Paint with Android graphics

I'm trying to plot a graph on a View using a canvas. So far so good it plots correctly as show in the next image:
Desired Output
once you tap on the screen the expected result should clear the screen and plot a new graph but instead draws on top of it resulting in this:
Actual Output
private List<Float> xPosList, yPosList;
private List<Path> pathList;
private Path path;
private Paint paint;
private final Paint clearPaint = new Paint();
public Plotter(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
this.xPosList = new ArrayList<>();
this.yPosList = new ArrayList<>();
this.pathList = new ArrayList<>();
this.paint = new Paint();
this.paint.setStrokeWidth(20);
this.paint.setColor(Color.GREEN);
this.clearPaint.setColor(Color.BLACK);
generateData();
}
private void generateData() {
int min = 5;
int max = 100;
double random = 0;
float xPos = 0;
float yPos = 0;
for (int i = 1; i <= 20; i++) {
random = min + Math.random() * (max - min);
xPos = 50 * i; //50 pixels
yPos = (float)random;
this.xPosList.add(xPos);
this.yPosList.add(yPos);
path = new Path(); //Create path
path.moveTo(xPos, yPos); //Add values to path
this.pathList.add(path); //Add path to pathList
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
generateData();
break;
case MotionEvent.ACTION_UP:
//invalidate();
break;
}
//invalidate(); //Refresh canvas
return true; //Activate event
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint p = new Paint();
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
p.setColor(Color.GREEN);
p.setStrokeWidth(10);
p.setStyle(Paint.Style.FILL);
/***
* Better use 50 by 50 pixels
*/
float startX = 0;
float startY = canvas.getHeight(); //Start at the bottom (max height)
float nextX = 0;
float nextY = 0;
for (int i = 0; i < this.xPosList.size(); i++){
nextX = this.xPosList.get(i);
nextY = canvas.getHeight() - (this.yPosList.get(i) * 10); //Add 50 offset
canvas.drawLine(startX, startY, nextX, nextY, p);
startX = nextX;
startY = nextY;
}
}
}
How do I properly clear screen?
I have tried
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
seen from other questions but it does not work.
Actually it does not have anything to do with your clear color - the screen gets cleared correctly. The problem is the xPosList and likewise the yPosList ArrayList.
As soon as the user taps the screen the generateData() function gets called which keeps adding elements to both ArrayList. But: you never clear those! So as soon as you tap the screen twice, the ArrayList's contain random data from the first and the second tap.
You need to clear those right before the for-loop:
this.xPosList.clear();
this.yPosList.clear();
for (int i = 1; i <= 20; i++) {
random = min + Math.random() * (max - min);
xPos = 50 * i; //50 pixels
yPos = (float)random;
this.xPosList.add(xPos);
this.yPosList.add(yPos);
path = new Path(); //Create path
path.moveTo(xPos, yPos); //Add values to path
this.pathList.add(path); //Add path to pathList
}

java android path animation

So I am nearly at the end.
I have been researching the whole day on how to do this.
Draw a path which grows(animation) from one point to another.
I have tried it with Matrix, but that just ended with turning my whole paths.
Here is a image of my project:
my project
My goal is to draw a animated path from one circle to the other.
Code:
public void init(#Nullable AttributeSet attr) {
circle = new Paint();
circle.setColor(Color.GREEN);
circle.setStyle(Paint.Style.FILL);
circle.setAntiAlias(true);
line = new Paint();
line.setColor(Color.GREEN);
line.setStyle(Paint.Style.STROKE);
line.setStrokeWidth(10);
line.setAntiAlias(true);
Collections.addAll(height, 100, 20, 50, 40, 70, 10, 50); // in percent
System.out.println(height.size() + " this is the size");
}
#Override
protected void onDraw(Canvas canvas) {
float y = getHeight() / 20 * 14;
float x = getWidth() / 8;
float radius = (canvas.getWidth() * canvas.getHeight()) / 40940;
for (int c = 1; c < 8; c++) {
System.out.println("at " + c);
canvas.drawCircle(x * c, y - ((getHeight() / 20) * (height.get(c - 1) / 10)), radius, circle);
points.add(new PointF(x * c, (y - ((getHeight() / 20) * (height.get(c - 1) / 10)))));
}
}
Please Help,
Thanks
you just need animate the path using ValueAnimator
create one path object
Path path = new Path();
and create animator
ValueAnimator animator = new ValueAnimator();
float startX = // starting circle x co-ordinate
float startY = // starting circle y co-ordinate
float endX = // end circle x co-ordinate
float endY = // end circle y co-ordinate
PropertyValuesHolder propertyX = PropertyValuesHolder.ofFloat("x",startX,endX);
PropertyValuesHolder propertyY = PropertyValuesHolder.ofFloat("y",startY,endY);
valueAnimator.setValues(propertyX,propertyY);
valueAnimator.setDuration(1000); // animation time
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float x = (float) animation.getAnimatedValue("x");
float y = (float) animation.getAnimatedValue("y");
path.lineTo(x,y);
invalidate();
}
});
valueAnimator.start();
and in onDraw() draw the path
canvas.drawPath(path,paint);

How to animate multiple paths in sequence in Android canvas?

I want to animate multiple paths in sequence, for example, I have
Path[] line and Path[] circle
so when I do for example
line[0].moveTo(x, y);
graphPath[j].lineTo(x, y);
I want to animate this part first and when
finish I want to add circle in same x,y postion
circle[0].addCircle(x, y, 10, Path.Direction.CW);
what I have done so far inside onDraw()
#Override
protected void onDraw(Canvas canvas) {
for (int j = 0; j < 2; j++) {
if (dataPoints2[j] != null) {
float x = leftPadding;
float y = height * getDataPoint(0, j) + topPadding;
graphPath[j].moveTo(x, y);
circlePath[j].addCircle(x, y, 10, Path.Direction.CW);
for (int i = 1; i < dataPoints2[j].size(); i++) {
x = width * (((float) i ) / dataPoints2[j].size()) + leftPadding;
y = height * getDataPoint(i, j) + topPadding;
graphPath[j].lineTo(x, y);
circlePath[j].addCircle(x, y, 10, Path.Direction.CW);
}
}
}
PathMeasure measure = new PathMeasure(graphPath[0], false);
length = measure.getLength();
ObjectAnimator animator = ObjectAnimator.ofFloat(Chart.this, "phase", 1.0f, 0.0f);
animator.setDuration(8000);
animator.start();
for (int j = 0; j < graphPath.length; j++) {
canvas.drawPath(graphPath[j], linePaint[j]);
canvas.drawPath(circlePath[j], circlePaint[j]);
}
}
public void setPhase(float phase){
linePaint[0].setPathEffect(createPathEffect(length, phase, 0.0f));
invalidate();
}
private static PathEffect createPathEffect(float pathLength, float phase, float offset)
{
return new DashPathEffect(new float[] { pathLength, pathLength },
Math.max(phase * pathLength, offset));
}
this will draw the circle then animate the line connecting the circle points
what I need is to animate the line and draw circle when the line reaches every x,y points

Drawing Bitmap (arrows) outside the circle on Canvas in Android

I have just begin to create some custom views in Android but I am facing problem while drawing bitmap (arrows) outside the circle.
Here is my code:
Canvas osCanvas = new Canvas(windowFrame); // Create a canvas to draw onto the new image
RectF outerRectangle = new RectF(0, 0, getWidth(), getHeight());
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); // Anti alias allows for smooth corners
paint.setColor(Color.parseColor("#FAFAFA")); // This is the color of your activity background
osCanvas.drawRect(outerRectangle, paint);
final Paint stroke = new Paint();
//paint.setColor(Color.TRANSPARENT); // An obvious color to help debugging
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT)); // A out B http://en.wikipedia.org/wiki/File:Alpha_compositing.svg
float centerX = getWidth() / 2;
float centerY = getHeight() / 2;
double rad = Math.min(getWidth(), getHeight()) / 2.5 - menuInnerPadding;
float radius = (float) rad;
stroke.setColor(Color.parseColor("#999999"));
stroke.setStyle(Paint.Style.STROKE);
stroke.setAntiAlias(true);
stroke.setStrokeWidth(5f);
osCanvas.drawCircle(centerX ,
centerY , radius - stroke.getStrokeWidth() +5f, stroke);
for(int i=0;i<elements.size();i++){
double angle =0;
if(i==0){
angle = startAngle;
}else{
angle = startAngle+(i * ((2 * Math.PI) / elements.size()));
}
elements.get(i).x = (int) (centerX + Math.cos(angle)*(radius));
elements.get(i).y = (int) (centerY + Math.sin(angle)*(radius));
float ang = (float) Math.cos(angle)*(radius);
Path path = new Path();
path.addCircle(elements.get(i).x,elements.get(i).y, radius, Path.Direction.CW);
if(BLINKER_ID == i){
if(blinkerPain != null){
osCanvas.drawBitmap(elements.get(i).bitmap,elements.get(i).x,elements.get(i).y,blinkerPain);
blinkerPain = null;
}
}else{
// here i am drawing the red arrows (bitmap images) But it's not fitting outside the circle.
osCanvas.drawBitmap(elements.get(i).bitmap,elements.get(i).x ,elements.get(i).y ,textPaint);
}
}
Here is my output
I think issue is with the padding.
I did code new write.
You should check this code.
#Override
protected void onDraw(Canvas canvas) {
Paint paint = new Paint();
paint.setColor(Color.BLUE);
paint.setStrokeWidth( 2 );
paint.setStyle(Paint.Style.STROKE );
canvas.drawColor(Color.WHITE);
float x = 400;
float y = 400;
float r = 200;
canvas.drawCircle( x , y , r , paint );
Bitmap icon = BitmapFactory.decodeResource(getContext().getResources(), R.mipmap.ic_launcher);
int length = 8;
float radian = (float)(Math.PI * 2f) / length;
for( int i = 0; i<length; i++ ) {
drawBitmap( canvas , icon , x , y , r, radian * i);
}
}
private void drawBitmap( Canvas canvas, Bitmap bitmap, float pivotX, float pivotY, float radius, float radian ) {
Matrix m = new Matrix();
m.postTranslate( -bitmap.getWidth()/2 , -bitmap.getHeight()/2 );
m.postRotate( (float)(radian * 180 / Math.PI) + 90 );
float drawHeight = radius + (bitmap.getHeight()/2);
m.postTranslate( ((float)Math.cos( radian ) * drawHeight) + pivotX
, ((float)Math.sin( radian ) * drawHeight) + pivotY );
canvas.drawBitmap( bitmap , m , null );
}

Chaos game android

I am currently developing a "chaos game" for android. For those that don't know what it is: you pick some random numbers, and according to a given set of rules a dot is drawn somewhere on a canvas; after many iterations you get a shape, always the same.
In this case, it is a fern.
here is my code:
MainActivity.java
public class MainActivity extends Activity {
DrawView drawView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
drawView = new DrawView(this);
setContentView(drawView);
}
}
DrawView.java
public class DrawView extends View{
int viewWidth;
int viewHeight;
int iterations = 10000; // how many dots
int myColor;
Paint paint = new Paint();
Random rand = new Random();
public DrawView(Context context) {
super(context);
myColor = context.getResources().getColor(com.*****.******.*****.R.color.ferncolor); //Green
paint.setColor(myColor);
paint.setAntiAlias(true);
}
#Override
protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld){
super.onSizeChanged(xNew, yNew, xOld, yOld);
viewWidth = xNew;
viewHeight = yNew;
}
#Override
public void onDraw(Canvas canvas) {
Double x = rand.nextDouble();
Double y = rand.nextDouble();
Double random;
for(int i = 0; i < iterations; i++){
random = rand.nextDouble();
if(random < 0.01){
x = 0.0;
y *= 0.16;
}
else if(random < 0.86){
x = (0.85 * x) + (0.04 * y);
y = (-0.04 * x) + (0.85 * y) + 1.6;
}
else if(random < 0.93){
x = (0.2 * x) - (0.26 * y);
y = (0.23 * x) + (0.22 * y) + 1.6;
}
else{
x = (-0.15 * x) + (0.28 * y);
y = (0.26 * x) + (0.24 * y) + 0.44;
}
Double posx = viewWidth/2.0 + x*viewWidth/7.5;
Double posy = y*viewHeight/10.2;
canvas.drawCircle(posx.floatValue(), posy.floatValue(), (float) 0.5, paint); //drawing dot at (posx,posy), size 0.5, with custom paint
}
}
}
My problem is that you have to wait for all the point to be drawn before you can see the view. That often leads to several awkward seconds blankness. What I would like is a "refresh" after every iteration (or every x iterations, depending on how much iterations I have).
I think that could be achieved via threading but I have no idea on how to achieve that.
Any ideas?
Thank you!
You can force a view to redraw by calling its invalidate() method. So you can try putting that at the end of your for loop.
More information here.
Also, invalidating too often could cause a performace slowdown, so if you want to draw 10000 dots, you could probably call invalidate only on every 500th iteration or something...

Categories

Resources