I'm new to Android (and Java for that matter), and I'm making a simple game. I'm stuck.
My problem is this:
I have 2 png images (a background and foreground) that take up the whole screen on startup. I now want to be able to set the width of the "drawn portion" of the foreground to the x-coordinate of ON_DRAG. My control method works fine; it's used like this:
g.drawRect(0, 0, scene.getLine(), g.getHeight(), Color.GREEN);
where scene.getLine() returns the x-value of the touch. So at this point I can draw a green rectangle above my images. But what I actually want is for those rectangle dimensions to "punch a hole" in my top-layer png (so the background is revealed beneath). I do not want to scale the foreground.
I have tried clipRect, but it doesnt work because I have other images that need to be drawn on top of these two, and clipRect prevents this. I have looked at a bunch of "PorterDuffXfermode" code, but cannot understand how to apply it to my situation, and cannot make it work. i.e. I can make a Paint with the PorterDuff "SRC" mode set, but I dont know how to define "source" and "destination" images so the Paint will work its magic. A final consideration with this is that even if the PorterDuff would work, Im not sure it would be practical given that I want this thing to run at 60fps.
Any suggestions?
Thanks.
You can call canvas.save() before a clip and canvas.restore() after your drawing to return the canvas to the sate it was in before you stared. Then you can draw your additional images.
Related
There is an issue with anti-alias when trying to draw multiple times at same place using the android Canvas.
First I'm initializing paint = new Paint(Paint.ANTI_ALIAS_FLAG) and then setting stroke cap to Paint.Cap.ROUND.
Then, if I call canvas.drawPoint(x, y, paint) once causes the following result:
While calling canvas.drawPoint(x, y, paint) multiple times (100 in this example) causes this:
I've created an example with minimal code to run this on GitHub: android-canvas-antialias
I noticed if I draw the points with a certain distance, the anti-alias seems to work as expected (first image). But drawing it with little offset causes the same anti-alias issue (second image).
Is there any setup that need to be done for this to work while drawing the points at same place? Or I simply may not be drawing at same place (or with very little offset)?
EDIT: the real issue is because I'm trying to draw a width variable line segment. See the MainActivity.drawSegment on git repository.
I don't think this is a problem, I mean, a bug itself. And even if solvable trivially I guess.
The pixels of the edge of the circle are draw with some alpha, e.g. a red pixel with 25% alpha if you overlay it with more 3 pixels with same alpha you will get a 100% red pixel.
A workaround would be manage all shapes created and check if some of them has the same size + position (maybe color too) and just draw one of them.
The link below explain how the Antialiasing works, might help.
http://web.cs.wpi.edu/~matt/courses/cs563/talks/antialiasing/methods.html
It works correctly. Anti-aliasing is when the edges of the shape are semi-transparent. When you multiply the shapes, the semi-transparent pixels become not transparent and you get "ragged" edges.
The solution is not to do this.
I have a transparent bitmap (clock face) that I redraw to mimic
a chronograph, and it works perfectly( overlaying different dials) use a base
empty faceplate PNG and draw the needles on top of it with a little trig/high school stuff
The problem: I need to loop thru this updating the values of the needles and overlaying
several dials., it works but the border gets grainy the more I loop thru it, if I use a non-transparent base faceplate it is fine... I've been trying all kinds of things/suggestions without success, I need the transparency to work for the overlaying.
Some resizing goes on as the final ImageView size where it is drawn can be different than the base faceplate size, tried createScaleBitmap, with a Matrix no difference stayed with the basic drawBitmap(bmp, rect1, rect2, myPaint)
Did use the ARG_8888 creating my bitmaps
have a method that returns the transparent bitmap with the needle worked out properly
I draw this on an ImageView with setImageBitmapm tried drawing on a bitmap first
but no difference
try to clear the bitmap before drawing the dials(PorterDuff.mode), no difference
Is there any trick or unknown way Android handles the transparent redrawing? Will setting Alpha to Zero make any difference? My Bitmap is already transparent.
easy now.
What I want eventually:
I want to have 2 bitmaps overlayed on a view. Same bitmaps with the one above have higher brightness than the below one.
Now when the user strokes(with touch event (like paint brush)) on the upper bitmap, I want those parts of the upper bitmap to go invisible.
For those who are familiar with adobe photoshop perhaps this will make more sense:
I want to draw a mask on an image being display so that only the unmasked parts remain visible. But the mask can be drawn from a brush with variable hardness/size.
How do I achieve this functionality? Direct me in in the line where I should research or give sample code.
Also, is it possible to draw strokes on an imageview with a brush which has variable hardness? I know that I can drawPath and drawArc on a canvas, but I do not know how to achieve the different brush strokes/styles.
Please pardon me if I haven't phrased my question right, or wasn't able to find similar duplicates.
You can use FrameLayout to overlay one image over other in Android and for Custom Masking search FingerPaint on google.
I think the best way is to do your own off-screen compositing, then render the composited image using an ImageView or perhaps a subclass with custom interaction. See this sample code for an example of how to do such compositing using the Porter-Duff transfer modes.
i try to paint an arrow png on canvas with a png bitmap behind it. so every time i rotate the arrow i have to reset the background bitmap of the canvas becouse otherwise i would see duplicates of the old arrows.
i reset the background with:
bMapLoad.eraseColor(0);
the problem is that sometimes it erases parts of the new arrow. sow that i sometimes only see a part of the arrow. i rotate it aber every 10-100 ms.
can someone help me?
i also tried:
bMapLoad=bMapcanvasBack.copy(bMapcanvasBack.getConfig(), true);
canvasLoad.setBitmap(bMapLoad);
this works fine but needs more memory. so is there a better way?
edit:
also
canvasLoad.drawColor(0, PorterDuff.Mode.CLEAR);
don't work
Try canvas.drawARGB(0,0,0,0) or, more concise canvas.drawColor(0) to clear it, then draw the bitmap again (canvas.drawBitmap(...))
The partial overdrawing may have a different reason though - synchronization between drawing and display. A common practice is to use double buffering. This means, you would draw on a offscreen canvas, and then exchange the underlying Bitmap with the visible canvas.
EDIT: some useful resources on double buffering with android:
An example here plus the book "beginning android games" also features a section on double buffering. The source code for the book can be downloaded here
Say I want to create a custom control that would look something like this:
http://karmalita.com/stuff/alpha1.png
The width of the popup balloon can change, and the relative position of the "pointer triangle" can change as well. Of course, additional graphics/text will be drawn on top.
I want it based on images, rather than trying to do the whole thing vector. And of course, the images have varying translucency, which is where the complications arise.
I know there are various ways of doing it (currently I use four images, one of which gets copied a bunch of times....it works but is messy), but I'm interested in finding the easiest, cleanest way. What would be nice would be if I could use a nine-patch for the main rectangle (below left), then draw the pointer triangle (below right) on top of it.
http://karmalita.com/stuff/alpha2.png
But of course that won't work, since the bottom edge of the rectangle will bleed through the pointer triangle, and the shadows will accumulate, etc.
Is there some Porter-Duff magic I can do?
Or should I simply mask the area of the pointer using an inverse clip rect, then draw the nine-patch (stretched appropriately), so it looks like this....
http://karmalita.com/stuff/alpha3.png
....then remove the clip rect, then draw the pointer triangle in the area where the clip rect was?
Or what? Is there an easier/better/more efficient way?
Although I'd love a solution for this specific problem, I'm mostly interested in a general solution for these sorts of scenarios.
Interesting one...
I was about to say "No, there's no way except the inverse clip-rect solution", but I have an (untested) idea:
When you add the arrow section to the regular 9-patch balloon, the result (luckily) is that all the pixels get more opaque.
Therefore (and here's the untested bit) you should be able to pre-calculate a modified version of the 'arrow' patch which - when applied on top of the regular balloon, gives the correct effect: For example the resulting arrow patch would have less shadow where the regular patch already contributes.
I'll let you think about the maths for that, but I guess it's pretty straightforward.