I am attempting to draw a triangular portion of a bitmap. I already know how to draw a filled triangle using path, and I already know that the answer may involve something called BitmapShader, but I can not find any clear documentation or examples to put it all together.
EDIT: After much flailing and experimentation, I am now nearly there. My code looks like this:
Paint paint;
Path path = new Path();
BitmapShader bms = new BitmapShader(shrub_bitmap,TileMode.REPEAT ,TileMode.REPEAT );
paint.setStyle(Style.FILL);
paint.setShader(bms);
path.reset();
path.setFillType(Path.FillType.EVEN_ODD);
path.moveTo(x1,y1);
path.lineTo(x2,y2);
path.lineTo(x3,y3);
path.close();
canvas.drawPath(path, paint);
paint.setShader(null);
The only remaining problem is that the bitmap from which the triangle is drawn is rooted to the screen coordinates. This means that when the triangle is being animated (i.e. being drawn at various points around the screen), it has the appearance of being a window allowing us to see a static image underneath. What I actually want is for the bitmap to be tied to the triangle so that the triangle looks like a solid object moving around. Any idea how to fix that?
for your second question:
try using canvas.translate(x1, y1) and moveTo(0, 0), lineTo(x2 - x1, y2 - y1) ...
Related
Firstly, I am trying to make a simple game in Java. I have a viewport that shows a tile map and I have a tank in the middle that moves by controlling the JScrollBars of the scrollpane in which the viewport resides in. So far everything has been going well, until I needed to rotate an image. Here is a picture of the game: Note: the tank body and tilemap are on seperate panels and do not share the same graphics.
Picture of non rotated tank body:
Essentially, I want to rotate a buffered image around its center (rotating in place) using arrow keys. I already have the code for the keys, and I also have a method to try and rotate the buffered image given a buffered image and angle in degrees (the angle is changed to radians in the method). This method will return a buffered image that is rotated correctly. Here is the code:
public static BufferedImage rotateImage(BufferedImage image, double angle) {
if(angle == 0)
return image;
else {
angle = Math.toRadians(angle);
double x = Math.abs(Math.cos(angle));
double y = Math.abs(Math.sin(angle));
int newWidth = (int) Math.floor(image.getWidth()*x + image.getHeight()*y);
int newHeight = (int) Math.floor(image.getHeight()*x + image.getWidth()*y);
BufferedImage rotated = new BufferedImage(newWidth, newHeight, image.getType());
Graphics2D tool = rotated.createGraphics();
AffineTransform transformer = new AffineTransform();
transformer.rotate(angle, image.getWidth()/2, image.getHeight()/2);
tool.drawImage(image, transformer, null);
tool.dispose();
return rotated;
}
}
However, as the title suggests, the image gets cut off at the top and left sides of the image when rotated as shown:
Picture of rotated tank body:
So I have looked at many different forums but I could not solve my problem. I could add whitespace around the image, but that interferes a lot with collision detection which I plan to do later on. I know that it has to do something with the original display being smaller than the display of the rotated image, and I have tried to translate accordingly in many ways. If I translate with this line of code specifically,
transformer.translate((newWidth - image.getWidth())/2, (newHeight - image.getHeight())/2);
Then the image (tank body) rotates without cutting, but bounces out of place as shown (I drew a rectangle to show where it was):
Picture of rotated tank with translation:
I also have tried negating the translations too but it only avails to funky movements.
So, I really have no clue how to solve this, and I have been spending too much time on this problem. I would really appreciate a helpful answer that directly edits my method if possible.
Answer
So here is the opening idea that I needed to realize to answer this problem.
The method to translate and rotate is meant so that the image is not cut off. However, it won't be around the center as intended as seen in the 3rd picture. But again, the method is not intended to recenter it. The painting code itself needs to account for this shift. I simply added variables to account for this:
xOffset = (newWidth - image.getWidth())/2;
yOffset = (newHeight - image.getHeight())/2
And simply subtracted these from where I was painting the tank's body.
Thanks to #camickr for the solution
When rotating a square sprite around the center point, the target image should be larger than the original image by a factor of the square root of 2 (approx. 1.41). For example, a sprite will not be clipped at a rotation angle of 45 °.
I hope this information helps you to solve your problem.
I am trying to draw a cushion like rectangle in processing like the pic shown. Is there any tricky way to use "light" to realize this? Does anyone have any idea about it? Thanks!
Pic reference: http://philogb.github.io/blog/2009/02/05/cushion-treemaps/
What you're talking about is called a radial gradient.
There are a number of ways to do it. One way would be to simply draw a bunch of circles. Here is a small example:
size(200, 200);
for(float diameter = 255; diameter > 0; diameter--){
noStroke();
fill(0, 255-diameter, 0);
ellipse(width/2, height/2, diameter, diameter);
}
You'll also have to limit your drawings to a rectangle shape. You might do that using the createGraphics() function to create a buffer, then draw the gradient to the buffer, then draw the buffer to the screen.
You should really break your problem down into smaller steps and take those steps on one at a time. First create a sketch that shows a simple gradient. Then create a sketch that uses a buffer. Get those both working by themselves before you combine them into one sketch. Good luck.
Another common method for implementing a collection of radial gradients of the type shown (a treemap) is:
create or acquire a single fairly high resolution image asset with a (jpeg/png) -- https://www.google.com/search?q=radial+gradient+box&tbm=isch
load the image
as you draw your boxes
optionally use tint() to tint the image green, red, etc. This works best with a grayscale source image.
scale your source image to the correct size for each box using the 5-argument image(img, x1, y1, x2, y2)
My question is: a bitmap had to be square or is possible delete the invisible parts around the colored image? I have a bitmap in a SurfaceView with an hand in the center and i want calculate the bounds of this hand deleting the invisible around it, cause i have problems with the onClick Method. Without calculate every X and Y, is possible know the bounds of the hand with a Method or other things? Thanks in advance.
The best thing you could do would be to take the picture of the hand and crop it down to the size of the hand.
This way, you'll have a smaller file and won't have to implement some kind of code work around.
About your first question: any bitmap that retains some level of transparency has to have an alpha channel so in your case a hand has an alpha channel thus you cannot just delete those alpha pixels, because if you do the transparent part will remain black. You will have to use either ARGB_4444 format or ARGB_8888 format to retain this alpha channel. As far as getting the bitmaps bounds, use a Rect or some bounding shape maybe an oval, to accurately know if your finger is touching it, you can't just know exactly if your touch is within the bounds of this hand because this hand image, at certain portions contain different widths, and heights, however you can test if your touch is touching your hand exactly by using pixel perfect collision. Here is how it works:
class drawingView extends View {
Rect rect = new Rect();
Bitmap bitmap = yourHand;
#Override
public void onDraw(Canvas canvas) {
canvas.drawBitmap(bitmap, x, y, null);
rect.set(x, y, bitmap.getWidth(), bitmap.getHeight());
invalidate();
}
public void onClick() {
if(rect.contains(event.getX(), event.getY(), && bitmap.getPixel(event.getX() - rect.left, event.getY() - rect.top) != Color.TRANSPARENT) {
// you know you exactly touched the hand even out of the transparent region
}
}
I started you off I'm sure you will understand what's going on here.
Hope this helps :)
The idea is to use a png file with the right transparency in place, which means the part around the hand should have the transparency .
Now for retaining the transparency of the image when using the BitmapFactory,make sure that your image is pulled in as ARGB_8888
I am working on a game where I have some bezier curves. At the moment, everything is fine and it's working as it should, although I do some complicated operation on this curves. To draw the curves I use a canvas and paths, like this:
private void refresh() {
mPath = new Path();
mPath.moveTo(start_x, start_y);
mPath.cubicTo(anchor1_x, anchor1_y, anchor2_x, anchor2_y, end_x, end_y);
}
public void draw(Canvas canvas, Paint paint) {
Path newPath = new Path(mPath);
Matrix mMatrix = new Matrix();
mMatrix.setTranslate(-mCamera.x1, -.mCamera.y1);
mMatrix.postScale(mCamera.getWidthRatio(), mCamera.getHeightRatio());
newPath.transform(mMatrix);
canvas.drawPath(newPath, paint);
}
The paint parameter is ussually the following one:
curvesPaint = new Paint();
curvesPaint.setColor(0xFFFFFFFF);
curvesPaint.setAntiAlias(true);
curvesPaint.setStrokeCap(Paint.Cap.ROUND);
curvesPaint.setStrokeJoin(Paint.Join.ROUND);
curvesPaint.setStyle(Paint.Style.STROKE);
curvesPaint.setStrokeWidth(canvas.getHeight() / 100f);
if (shadow)
curvesPaint.setShadowLayer(canvas.getHeight() / 50f, 0, 0, 0xAAFFFFFF);
else
curvesPaint.setShadowLayer(0, 0, 0, 0xAAFFFFFF);
My question is: how can I make the curves more beautiful? At the moment, they're only white (or white with a white shadow). I want to be able to draw them with a nice gradient or model on them and I have no idea how to do that. I was thinking about the setShader function of the Paint class but I don't know if I can use it for my purpose or how to use it. Other solutions, like drawing multiple paths one above the other, is clearly impractical due to low fps.
I suggest you start looking at using OpenGL or third-party wrapper libraries such as libgdx. Canvas is meant for relatively simple graphics. I don't think it takes advantage of the devices GPU. To take advantage of the full power of the GPU, you will need to use OpenGL.
Im making a program using Java for android.
I'm drawing alot of rectangles on a bitmap using 4 lines connecting. ATM the lines are black and the background is white, i want to fill these "boxes" with colour and i cant figure out how to do it.
to change from drawing 4 lines into making a box from the start is not an option, i have to draw lines that form a box.
im thinking of something that takes an argument of x,y in the middle of the "box" and then filling it with pixles until it hits the edge of the box but i cant get it to work.
it needs to be reapeteble too, i have alot of boxes to fill.
im using android 2.1 with API 7
You can quite simply do this with a Path. It works as you're talking about -- move from point to point "drawing lines" -- but when you're done you can fill it.
Paint paint = new Paint();
paint.setStyle(Style.FILL);
// set other paint parameters, like color...
...
Path path = new Path();
path.moveTo(startX, startY);
path.lineTo(startX, startY + 50);
path.lineTo(startX+50, startY + 50);
path.lineTo(startX+50, startY);
canvas.drawPath(path, paint);
Use Paths. You can create your lines in a path, and then when you draw the path on the canvas, it will filled with the paint. You can also add a stroke to the path to add a border to the shape.