AS3 Render Shape to Bitmap with Antialias - actionscript-3

I have a drawn a Circle Shape in AS3. I want to render the Circle into a Bitmap with nice/antialiased Edges. Because I want it to work on Mobile Devices (Air Apps are limited to stagequality = low) I need a workaround. Any custom shape to bitmap renderer available?

Not sure this solution would work for Air Mobile Apps, but worth looking into.
Didier Brun # ByteArray.org posted an API used to draw primitive shapes (as BitmapData, not from Vector draw calls either), which might help you get your circles to draw the way you want.
http://www.bytearray.org/?p=67
Code Snippet (from that URL):
// create the BitmapData to work on
var pixels:Raster = new Raster(320, 240, true);
// draw stuff
pixels.drawRoundRect( new Rectangle ( 20, 20, 200, 100), 18, 0xFF00FFFF );
pixels.drawRect( new Rectangle ( 70, 70, 100, 100 ), 0xFF009900 );
pixels.filledTri( 40, 40, 80, 110, 50, 30, 0xFF998811 );
pixels.aaCircle(100, 100, 40, 0x77AA88 );
pixels.circle(40, 40, 30, 0xFF000000);
pixels.line(10, 10, 60, 80, 0xFF000000 );
// show it
addChild ( new Bitmap ( pixels ) );
Hopefully the library / source code is compatible for your project! :)

Have you consider using the drawWithQuality method?
The drawWithQuality() method works exactly like the draw() method, but instead of using the Stage.quality property to determine the quality of vector rendering, you specify the quality parameter to the drawWithQuality() method.

StageQuality.LOW is going to make your bitmap quality low if you're using draw() because the source will be of low quality whether it's on the DisplayList or not.
I don't think there's a way around this.. You'll have to load in circle graphics or import images to use.

If it is only something simple as circle, you can synthesize smooth image pixel by pixel. Create BitmapData of sufficient size and loop on pixels. On every pixel, compute distance from center - if it less than circle radius - half of pixel diagonal, set pixel to circle color. If it greater than circle radius + half of pixel diagonal, call setPixel32(x, y, 0).
Pixels that won't pass both conditions are near the edge - to do exact antialiasing, you must compute how much of pixel is covered by circle. Maybe you can find some convincing simple approximation. Good luck!
Update:
OK, I think I can remember simpler approach... You can draw your circle or any shapes two times bigger than they should be, then draw that bitmap into another with scale 0.5 (set through matrix) and smoothing on. That would be supersampling 4x. If stage quality doesn't affect bitmap smoothing, it should work.

In ActionScript 3 bitmap is created from BitmapData, so you need to create if first with
_bitmapData = new BitmapData(..
BitmapData has method draw, passing DisplayObject instance (Sprite, MovieClip or other) to it as parameter, will draw it's content into BitmapData.
Example:
var c:Sprite = new Sprite();
c.graphics.clear();
c.graphics.beginFill(0x00FF00, 0.5);
c.graphics.lineStyle(2.0);
c.graphics.drawRectangle(0, 0, 100, 100);
c.graphics.endFill();
var bd:BitmapData = new BitmapData(100, 100);
bd.draw(c);
var bitmap:Bitmap = new Bitmap(bd);

Related

Draw Rectangle and see it on batch without any texture

I am making a rectangle :
rect = new Rectangle();
rect.x = 40;
rect.y = 100;
rect.setSize(100,100);
and then also drawing some texture on the position of rectangle like:
batch.draw(myTexture, rect.x , rect.y, rect.width, rect.height);
Now what i want to do is also see the shape of rectangle like i must see some boundary so that i can see my rectangle boundary as well as my texture. And i need this for debugging purposes as the texture is complex like somewhere the background is transparent so i want to remove the collision from those places and that is why i am thinking if i could see both the rectangles and the sprite it would be great.
Although i tried doing this:
shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
shapeRenderer.setColor(Color.RED);
shapeRenderer.rect(0,0,100,100);
shapeRenderer.end();
I thought the above code would help me draw the texture as well as see the rectangle but turns out i could see only the rectangle's boundary and not the texture.
Here is the output:
In the image , you can see a red rectangle and that is where i was trying to debug my bar (a bar of yellow color was also supposed to be shown here) but my yellow doesn't appear as this red-boundary rectangle overlapped my bar.
To be clear, i want to see the shapeRenderer right above the texture and be able to see the both of them
So i found the answer,
As you know i wanted to appear a rectangle over my texture so that i could see both - my texture and my shapeRenderer shape but instead i could see only my shape and not the texture.
Problem was that What is was doing is i began the batch and inside that i wrote the code for drawing to the batch and also the code for drawing the shapeRenderer to the batch like this:
batch.begin();
batch.draw(texture,0,0,0,0);
shapeRenderer.begin();
shapeRenderer.rect(0,0,0,0);
shapeRenderer.end();
batch.end();
The above code replaces my texture as it can only draw one thing at the coordinates 0,0 so first it draws the texture at 0,0 and then the shaperenderer at 0,0.
The solution was:
To draw the shapeRenderer separately and not within the batch.begin() and batch.end() like:
batch.begin();
batch.draw(texture,0,0,0,0);
batch.end();
shapeRenderer.begin();
shapeRenderer.rect(0,0,0,0);
shapeRenderer.end();

LibGDX - Draw clipped sprite

I am surely overlooking something, but is there an easy to draw for example only half a sprite in LibGDX? I originally thought I could do this with setBounds() but this distorts the sprite and does not clip it.
do not know if this is what you want, or is the most efficient way but that's what I happened to read your question, I hope I understand and serve you this:
Variable class:
Texture testTexture = new Texture (Gdx.files.internal("badlogic.jpg"));
In render method for example:
//batch is a SpriteBatch.
batch.draw(testTexture, 50, 50,
0, 0,
testTexture.getWidth() /2,
testTexture.getHeight());
this is the method in SrpiteBatch.class:
public void draw (Texture texture, float x, float y, int srcX, int
srcY, int srcWidth, int srcHeight)
Now for example in you sprite (simple test):
batch.draw(yourSprite.getTexture(), 50, 50,
0, 0, yourSprite.getTexture().getWidth() /2,
yourSprite.getTexture().getHeight() );
Edit Note:
to re-look the answer, I thought it would be nice to say that this makes, show only one area of the texture as you say, but perhaps should be noted that the texture remains the same size, I say this because if you texture used to detect collisions, keep in mind, that although half display, texture remains as large than the original
There was also Scissors class:
http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/scenes/scene2d/utils/ScissorStack.html
I think I tried it once...but it worked well on desktop and not on android...so I didn't use it. Maybe it's fixed meanwhile.

AS3 erase bitmap that has filters

So I use bitmap.bitmapData.draw(erase,null,null,"erase"); to erase part of a bitmap that has the sprite called erase over it. The problem is that I need the bitmap to be blurred, and after I apply a blur filter the bitmapData.draw function doesn't work anymore. Meaning absolutely nothing happens. I tried using bitmapdata.applyFilter, which almost works except when I erase near a blurred edge it "unblurs" itself.
var erase:Sprite=new Sprite();
erase.cacheAsBitmap = true;
var blur:BlurFilter = new BlurFilter(10,10,10);
var blurs:Array=new Array();
blurs.push(blur);
bitmap=new Bitmap(bitmapdata);
bitmap.blendMode = "layer";
bitmap.y=-10;
bitmap.x=-10;
Refs._stage.addChildAt(bitmap,0);
also:
erase.graphics.beginFill(0xFF0000);
erase.graphics.drawCircle(stage.mouseX+10,stage.mouseY+10,35);
erase.filters = blurs;
erase.graphics.endFill();
bitmap.bitmapData.draw(erase,null,null,"erase");
It's just how the erase draw works. It erases pixels based on the alpha value of the object being drawn in erase mode. Where the alpha is above 0.5, that pixel get its alpha dropped to zero. Other pixels are not touched. This is what you experience when you draw with erase, then blur, then draw with erase again. No, Flash is not intelligent enough to do erase-blur, you might have to do it yourself. You might try drawing a transparent BitmapData with BlendMode.ERASE to do a blur-erase, but I don't expect it to return a blurred bitmap with blurred erased regions.

ActionScript drawRoundRect rendering blurry corners

I'm using the AS3 drawRoundRect function as in the following snippet:
g.lineStyle(1, 0x808080, 1, true);
g.drawRoundRect(0, 0, 100, 24, 12, 12);
As you can see, pixel hinting is on.
The problem I'm having is corners being anti-aliased way too much, they are way too blurry and not even symmetrical on the above snippet. Frankly, the drawRoundRect function draws the ugliest rounded rectangles that I've ever seen.
Is there a way to make AS3 draw more crisp rectangles?
Thanks!
:)
fills are rendered much better than lines. as you can see here:
const thickness:Number = 1;
g.beginFill(0x080808);
g.drawRoundRect(0, 0, 100, 24, 12);
g.drawRoundRect(thickness, thickness, 100 - 2 * thickness, 24 - 2 * thickness, 12 - thickness);
g.endFill();
g.lineStyle(thickness, 0x080808, 1, true);
g.drawRoundRect(0, 50, 100, 24, 12);
well, it is not SOOOOOOOOOOO unincredibly better ... :-S ... but at least its symetric ... and the smudges on the corners are more like little beads ... :-D
greetz
back2dos
I've had similar problems in the past. It usually came down to one of the movieclips along the display path not being on an even pixel. Flash then tries to render fractional pixels, which it can't do, which caused distortion and blurriness.
So, make sure all your movieclips/sprites are on an even pixel (I know you're drawing the rect on even pixels, but if the displayobject it belongs to, or any of its parents aren't on an even pixel, it would be causing the problem).
I've had the same deal, as well. One hacky trick you could try is to apply a minor blur filter to the parenting object.
It looks like you're using the drawRoundRect method of the Graphics class.
If the object you're working with is a UIComponent, you could try using the drawRoundRect method of UIComponent. It takes an Object for the cornerRadius value, rather than setting ellipse width and height values. I'm not 100% sure that the cornerRadius value isn't converted into ellipse width and height, but it seems like it'd be something to try.
Also, you could try the GraphicsUtil class's drawRoundRectComplex. It takes a Number for each corner's radius. Again, not completely sure that it doesn't eventually use the same underlying mechanics as drawRoundRect.
When you using drawRoundRect set X to be half of thickness, and then thickness will be on rounded pixel. In this your case try:
g.lineStyle(1, 0x808080, 1, true);
g.drawRoundRect(0.5, 0.5, 99, 23, 12, 12);

Changing a sprites bitmap

As of right now, I am trying to create a tiling effect for a game I am creating. I am using a tilesheet and I am loading the tiles to the sprite like so...
this.graphics.beginBitmapFill(tileImage);
this.graphics.drawRect(30, 0,tWidth ,tHeight );
var tileImage is the bitMapData. 30 is the Number of pixels to move retangle. then tWidth and tHeight is how big the rectangle is. which is 30x30
This is what I do to change the bitmap when I role over the tile
this.graphics.clear();
this.graphics.beginBitmapFill(tileImage);
this.graphics.drawRect(60, 0,tWidth ,tHeight );
I clear the sprite canvas. I then rewrite to another position on tileImage.
My problem is....
It removes the old tile completely but the new tile positions farther to the right then where the old bitmap appeared.
My tile sheet is only 90px wide by 30px height. On top of that, it appears my new tile is drawn behind the old tile. Is there any better way to perfect this.
again, all i want is for the bitmap to change colors
You could try to load the whole tilesheet in your sprite, and then redefine the scrollRect property each time you need to.
this.scrollRect = new Rectangle( 30, 0, tWidth ,tHeight );
Note that you can't just edit scrollRect.x, .y, .width or .height ; you have to redefine a new Rectangle each time.
Using scrollRect will probably be much faster that redrawing part of the bitmap.
You can read this excellent article from Grant Skinner for more informations about scrollRect.