I have been trying to work on a simple code for two days now. I have tried all alterations but none seems to be working.
I am trying to draw vertical rectangles with different colors.
In the first one, I am using only one Rect variable and moving the coordinates. Here is the relevant part of the code.
Rect myRect1=new Rect();
Random colorMe=new Random();
for(int j=0;j<5;j++){
myRect1.set(myCanvas.getWidth()/5*j, 0, myCanvas.getWidth()/5*j, myCanvas.getHeight());
paint.setColor(Color.rgb(colorMe.nextInt(255), colorMe.nextInt(255), colorMe.nextInt(255)));
myCanvas.drawRect(myRect1, paint);
}
Other alteration which I tried was through an array.
Here is the code.
Rect[] myRect=new Rect[5];
Random colorMe=new Random();
for(int j=0;j<5;j++){
myRect[j].set(myCanvas.getWidth()/5*j, 0, myCanvas.getWidth()/5*j, myCanvas.getHeight());
paint.setColor(Color.rgb(colorMe.nextInt(255), colorMe.nextInt(255), colorMe.nextInt(255)));
myCanvas.drawRect(myRect[j], paint);
}
Can somebody please help me what is the problem actually there?
The first thing that seems obviously wrong (there might be more):
The minimum x-coordinate of your rectangle is myCanvas.getWidth()/5*j
The maximum x-coordinate of your rectangle is myCanvas.getWidth()/5*j
They are both the same value, so your rectangle is degenerate.
Offtopic, but very relevant: whenever you run into a problem like this, you need to break it down into smaller parts until you get it to do something. This will help you understand what's wrong:
Extract all subexpressions (like the color, and the generated x/y values) into local variables so you can easily inspect them in the debugger
Replace the random color by a predefined color (COLOR.YELLOW), to rule out the random element
Replace the caclulated rectangle by a fixed rectangle (say (10,10) - (20,20)) to rule out the coordinate calculations.
Replace the loop, to rule out the loop.
Your rect has a width of 0px. The parameters of the set() function are, in order, left/top/right/bottom. You use the same value for left and right, so the width is (right-left)=0.
Let's see your coordinates, first:
myRect1.set(myCanvas.getWidth()/5*j, 0, myCanvas.getWidth()/5*j, myCanvas.getHeight());
Top left corner has the same x coordinate as the bottom right corner, so you are drawing a rectangle with 0 width.
Add this line
myRect[j] = new Rect()
before
myRect[j].set(myCanvas.getWidth()/5*j, 0, myCanvas.getWidth()/5*j, myCanvas.getHeight());
Related
As I am a beginner of Android developement, I need someone to give me an answer or any comments on my question.
When I draw a simple rectangle on a view with the following code, the rectangle doesn't show in the way in which I would expect.
canvas.drawLine(0, 0, getWidth(), getHeight(), framePaint);
wrong
But when I changed it like this, it shows properly.
canvas.drawRect(1, 0, getWidth(), getHeight()-1, framePaint);
Correct
That looks like the left and the bottom lines are clipped out of the view.
I was expecting that the position of view starts zero-indexed such as 0 ~ (size of view)-1. Do I understand wrong or did i do something wrong?
The framePaint is configured like this;
framePaint = new Paint();
framePaint.setColor(Color.rgb(255,0,0));
framePaint.setStrokeWidth(1);
framePaint.setStyle(Paint.Style.STROKE);
Here's what happens:
When you subtract one from the total pixels, it draws the line(s) in the image, not outside of it.
Also the "1" at the start also helps the code stay in the canvas.
You may want to try replacing the 1's in the code with 2's, as the canvas uses an extra pixel to automatically remove "aliasing".
I would like to detect collisions between shapes dynamically drawn on a canvas (SurfaceView) for an Android game.
I can easily use intersect method of Rect or RectF objects but the result is not very good (see picture below where I have a "false" detection).
I don't want to use Bitmap so it's impossible to use the "pixel perfect" method.
Do you know a way to do this for circle, rect, triangle and other basic shapes intersection ?
Thx for help ;)
For a good collision detection you have to create your own models behind. In those models you specify the conditions that two objects colide.
For example, a circle is described by the center position and by the radius. A square is described by the left down corner and by the edge length.
You don' t have to describe all possible poligons, you can use the so called bounding boxes, meaning that, for a complex random poligon you can use a square or whathever shape fits it best(also you can use multiple shapes for a single object).
After you have the objects in mind you compute the condition that each one of them will colide with all other shapes including itself.
In your example The sphere and the square colides if the distance between any corner of the square is greater than the circle's radius.
Here you can read more http://devmag.org.za/2009/04/13/basic-collision-detection-in-2d-part-1/
This problem can get very complex, keep it simple if you want something simple.
Here is a directly applicable method I use in my own game to detect circle and rectangle intersection. It takes the ball (which is a view in this case) and the rectangle (also a view) to be checked for collision with the ball as parameters. You can put the method in a Timer and set the interval you want the circle and rectangle to be checked for collision.
Here is the method:
public boolean intersects(BallView ball, Rectangle rect) {
boolean intersects = false;
if (ball.getX() + ball.getR() >= rect.getTheLeft() &&
ball.getX() - ball.getR() <= rect.getTheRight() &&
ball.getY() + ball.getR() <= rect.getTheBottom() &&
ball.getY() - ball.getR() >= rect.getTheTop())
{
intersects = true;
}
return intersects;
}
getR() gets the circle's radius
getX() gets the center of the circle's X position value
getTheLeft() gets the rectangle's left X value
getTheRight() gets the rectangle's right X value
getTheTop() gets the rectangle's top Y value
getTheBottom() gets the rectangle's bottom Y value
If you can't directly use this method in your code you can still conjecture the logic it entails to implement it where it would work for you. It detects all collisions without using pseudo-collision detection like a collision box for the circle.
Good luck! And if you have any questions feel free to ask, I'm here to help!
To know if a polygon in 2d is colliding with a circle, you can test, for each of its lines, where is the point on the line that is closest to the center of the circle (this might help).
Then, check if the point you found is between to two corners that make the line - that is, that the point is actually on the line, and not just on its continuation - and if the distance of that point to the center of the circle is smaller or equal to the radius of the circle. If both are true for any of the lines of the polygon, you have a collusion. You also have to check for the edge cases where the corners of the polygon might be in, or touching the circle.
For two circles, this is easier. Check the distance between the centers, and compare it to the sum of their radiuses. If the distance is smaller or equal to the sum, you have a collusion.
I got stuck with canvas.drawLines().
My application displays track om map view, but the resulting lines are awful.
Did anyone see such behavior? I.e, lines doesn't have same width, are not even "square", and are rhombus, and sometimes even disappear!
I've tested with for(){drawLine()} instead, and drawPath instead - same issue.
Screenshot took on 10" tablet 1280x800, Fujitsu. Lenovo tablet shows the same.
http://jpegshare.net/c8/1d/c81daa6cff15e3d14cb1268679bb1af1.png.html
borderPaint = new Paint();
borderPaint.setAntiAlias(true);
borderPaint.setStrokeWidth(5);
borderPaint.setStyle(Paint.Style.STROKE);
borderPaint.setColor(Color.WHITE);
//borderPaint.setAlpha(190);
fillPaint = new Paint();
fillPaint.setAntiAlias(true);
fillPaint.setStyle(Paint.Style.STROKE);
fillPaint.setStrokeWidth(3);
fillPaint.setColor(Color.RED);
....
canvas.drawLines(linepoints, 0, linepoints_count, borderPaint);
canvas.drawLines(linepoints, 0, linepoints_count, fillPaint);
where linepoints is array of track lines to draw. Each line is set of 4 float numbers.
Well, I figured out my problem. Hope this can help someone.
Before drawing lines, I do
canvas.translate(X, Y);
where X and Y values are HUGE. Like 10E+6..10E+7 or something.
When I draw lines, their xy values are huge too, but negative, hence in screen coordinates this xy+XY give something inside a screen - but this fact matters and produces issue described in my own first post.
Why this is happening? I found a clue. When drawLine algorithm tries to draw a line, it messes up with line coordinates (division, multiplication) and since machine arithmetic is limited in precision, algorithm gets wrong numbers.
How this was solved?
I dicarded canvas.translate(), and calulate screen coords on the fly, just before drawing.
Now, like that
screen_line_coords_x = line_coord_x - X; //X is offset applied in translate.
screen_line_coords_y = line_coord_y - Y; //Y is offset applied in translate.
canvas.drawLine(screen_line_coords_x, screen_line_coords_y, ...);
... or drawLines() or drawPath() - all give good results.
Hope this might help.
I´m facing same thing.
However, why are you using so huge offset, since the screen is about 1280x800 resolution ?
I believe that system coordinates gets too far from the real display coordinates causing wrong calculations at translation / rotation / scaling operations.
Try to revise your calculations in order to work inside of the display coordinates.
Can somebody help me understand how does path.lineTo(x,y) actually work. I am trying to draw a simple straight line in a finger paint type of app. Here is an example I tried:
mPath.reset();
mPath.moveTo(0, 0);
mPath.lineTo(480, 800);
But the line goes only from 0,0 to 240, 400 - always only a half of distance as I move my finger over the screen. (the real programme has startX, startY and x,y touch coordinates instead of 0,0 & 480,800)
Maybe this piece of code will work for you:
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
Path mPath= new Path();
mPath.moveTo(0, 0);
mPath.lineTo(480, 800);
p.setColor(0xff800000);
canvas.drawPath(mPath,p);
Also, the (480, 800) coordinate, is it still inside your screen?
The Path commands work exactly how you expect them to work and the above command should draw a line from top left to bottom righ corners in a view fully covering a 480x800 screen .
Check the follwoing:
The view covers all screen
The is no other view overlaping it
The coordinates are relative to top left coordinate of view. Check that view top left is on top left of screen
Regards.
Thanks to Goz and others who helped me truobleshoot this, it came out that Paint was doing it with this settings:
mPaint.setPathEffect(new CornerPathEffect(1000))
When this is removed or set to null, lineTo goes all the way. One just did not expect at first that Paint would do this but this corner rounding effect can shorten a straight line.
This is probably an easy one for Android experts. I am trying to draw into a Bitmap via a Canvas. I want exact colors, no anti-aliasing, and lines located at exact absolute coordinates within the Bitmap. Sometimes the lines are in the correct position and sometimes they are offset by 1 pixel. I have a feeling this has something to do with scaling. But I'm not sure. Here's the code:
Paint mPaint = new Paint();
mPaint.setColor(Paint.WHITE);
mPaint.setStrokeWidth(0);
mPaint.setAntiAlias(false);
mPaint.setDither(false);
mPaint.setStyle(Paint.Style.STROKE);
drawingContext.mycanvas.drawLine(20, 0, 10, 10, mPaint);
This actually draws a line from (19,0) to (10,9). Why?
I'll answer. I had to give up on this and write a Bresenham algorithm, setting pixels one by one. That works OK for what I'm doing. I suspect a drawLine bug when drawing left to right, bottom to top lines.