As3 Actionscript drawing within the outlines - actionscript-3

I am developing a coloring game using adobe air and as3. I have an image with black outline and the user can draw / color the image using a pen tool. I need help to figure out how can I restrict the user to draw within the outlines only. Masking the image with the line-graphics is something I have tried but it hangs the application. Any hint / suggestion towards the solution is appreciated.
following is the code on mouse_down event
_dot = new MovieClip();
_dot.graphics.lineStyle(lineSize, color);
_dot.graphics.moveTo(img.mouseX,img.mouseY);
img.addChild(_dot);

Let's say, the area you are drawing on is a DisplayObject with an instance name of Canvas. What you need is to check if the mouse is on Canvas or not.
In order to do so, you want to use the DisplayObject.hitTestPoint(...) method with the shapeFlag set to true (if it is false, it tests the point against the object's rectangle bounding box, which would produce the wrong results for any non-rectangular or rotated shapes).
So, you do as following:
var P:Point = new Point;
// First, convert coordinates to Stage coordinates,
// because the method requires so.
P.x = Canvas.mouseX;
P.y = Canvas.mouseY;
P = Canvas.localToGlobal(P);
// Now, test if the mouse is within the given canvas.
if (Canvas.hitTestPoint(P.x, P.y, true))
{
// The drawing should happen here.
}

Related

Changing Shape Dynamically Using Mouse In As3

I want to dynamically change the shape of a shape in as3. Say for example, on clicking and dragging on shape square the shape should change according to my mouse movement, direction. I have pasted a link below which display my requirement, selecting one shape and edit edges option, then click the shape and drag, the shape will change according to mouse movent and direction based on some math calculation. Is that possible in AS3.
http://www.shodor.org/interactivate/activities/Tessellate/
Yes, it is possible to make this type of programs.
I suggest you looking into Sprite's graphics object. It has the API to draw primitives, lines and curves.
The reason why you should use Sprites in this case is because it extends InteractiveObject => they support user input, like mouse or touch inputs.
Here's an example of creating triangle:
var s:Sprite = new Sprite();
s.graphics.lineStyle(1, 0x000000); // optional
s.graphics.beginFill(0xff0000); // optional
s.graphics.lineTo(0, 100);
s.graphics.lineTo(100, 100);
s.graphics.lineTo(0, 0);
s.graphics.endFill();
addChild(s);
You can combine mouse events to track input and event ( enter frame in particular ) to redraw your shape depending on the mouse position.
To redraw the shape, you might want to call graphics.clear() method on that object to erase it from the screen.

as3 crop image loaded as MC

Hi this kills me :) I am using senocular for as3 move,rotate,scale,skew loaded image into MC and works great, but spent a lot of time, can't find nice solution for cropping such MC (with loaded image) with mouse. Do someone have solution (code) for this?
To display the cropped area, all you need to do is apply a mask, which is just another Display Object.
I haven't used Senocular's code for this, but if you make the mask the target of his move / scale code, then you can easily implement cropping. There's plenty on masking in the Adobe docs: http://livedocs.adobe.com/flex/3/html/help.html?content=05_Display_Programming_28.html
In practice, you have to hide the resize / move controls when cropping, and vice-versa, which is why tools like Flash itself, or Photoshop, have separate transform and crop modes.
From Senocular's docs:
// import for the Transform Tool classes used
import com.senocular.display.transform.*;
// create a box object to interact with
var box:Sprite = new Sprite();
addChild(box);
box.graphics.beginFill(0xAACCDD);
box.graphics.drawRect(-50, -50, 100, 100);
box.x = 100;
box.y = 100;
// create the Transform Tool
var tool:TransformTool = new TransformTool(new ControlSetStandard());
addChild(tool);
// select the box with the transform tool when clicked.
// deselect when clicking on the stage
box.addEventListener(MouseEvent.MOUSE_DOWN, tool.select);
stage.addEventListener(MouseEvent.MOUSE_DOWN, tool.deselect);
Just do this, but box needs to be the mask of your movie clip, so that when you resize it, you will crop the movie clip.

AS3 Is it possible to duplicate a Shape object?

I'm trying to make a shape available for duplicating. Here's an explanation of what I've done, what I'm trying to do, and where I'm stuck:
Drew a shape manually in the Flash IDE (paintbrush).
Created a new movieclip containing the shape; exports as a class.
Instantiate the class (var mc:MovieClip = new shapeMovieClip()).
Add a reference to the shape in mc that I want (var myShape:Shape = mc.getChildAt(0) as Shape;
This works perfect and I now have my shape, but how can I duplicate it without instantiating the parent MovieClip class - is it possible?
I've tried creating a new shape and using the copyFrom() graphics method with no avail, I believe this method just copies draw calls when they're made on the referenced graphics and instead I just have a reference of a shape that's already been drawn.
Right now I'm extending the movieclip as a sprite instead, instantiating, pulling the shape from the parent and saving its reference, and then nulling the sprite. Does anyone know of a better, more lightweight, strategy for duplicating Shapes in this manner?
Basically depends on whether you need to scale your shapes. If you don't, and you can work it out with a fixed sized bitmap representation of the shape, then you will get much better performance drawing your shape to a BitmapData (it's called rasterisation) and instanciating Bitmap objects (as other commenters have pointed out). The code would go something like this:
var base:Sprite = new shapeMovieClip();
var bmd:BitmapData = new BitmapData(base.width, base.height, true, 0);
bmd.draw(base);
var clip1:Bitmap = new Bitmap(bmd);
var clip2:Bitmap = new Bitmap(bmd);
If you do need to scale the clips, you will get pixelation using bitmaps. When scaling down Bitmap.smoothing can help to some extent (also when rotating), but if you need to scale up, you will probably have to use some kind of mip-mapping. This is basically creating a few bitmaps of the shape at different scale levels, and then swap them depending on the current scale. Coding this has some complexity (using a helper parent to adjust the scale can help) but it will definitely perform better than using many shape symbols (with or without a sprite parent).
This is very old, but it still comes up high in Google, so I just wanted to share a true shape duplicating method:
var shapeonstage:Shape = shapeMadeInIDE;
var g:Vector.<IGraphicsData> = shapeonstage.graphics.readGraphicsData();
var shapecopy:Shape = new Shape();
shapecopy.graphics.drawGraphicsData(g)
And boom. It works. Had to share this because it would have helped me a looooong time ago and in so many ways.
UPDATE:
There is some clarification I'd like to add why you would want to use this method, for duplicating AND for storing references to Shapes that are within an swf.
If you target a Shape object on the stage or in a movie clip, the Flash Rendering engine does something strange. It will RECYCLE Shape objects to render new graphics thus making your Shape reference point to a COMPLETELY different rendering.
For example:
Create an fla with a movieclip.
Inside the movie clip make 10 frames.
On each frame, draw a different shape
In your code, get a reference to the shape (The Shape on Frame 1)
Draw and verify your shape (draw to a bitmap then put the bmp on stage)
Now let the flash engine play for 5 frames
Draw and verify your shape again
The second time you draw your shape without EVER reassigning your shape reference, will SOMETIMES yield a completely different shape.
Just know, this little quirk can leave you pulling your hair out if you don't know what you're looking for :)

Points from Sprite.graphics in AS3

I need to know where the Sprite.graphics start to do some stuff. When I add the sprite to my MovieClip, (x,y) coordinates are (0,0) but I need to know coordinates from Sprite.graphics, not Sprite. There are some images so clarify what I want:
I have this board where user can draw some forms (lines, arrows, polygons, etc.) When the user draw a line, I interpret that Sprite is created (with Sprite.graphics inside it, the real form).
How can I catch the point where Sprite.graphics is created? Actually I can't because Sprite.graphics is read-only.
Thanks!
EDIT: some source code
line = new Sprite();
line.graphics.moveTo(posX,posY);
line.graphics.lineStyle(10);
line.graphics.lineTo(endposX,endposY);
Global.board.addChild(line);
To get the bounds of visual part, you can try:
var bounds: Rectangle = line.getBounds(line);
There is also a getRect() method, but that leaves out space taken by strokes.
You cannot access the graphics data like that. Your best chance would be to save the coordinates posX and posY yourself when the line is being drawn.

Multiple clicking regions on HTML5 canvas?

I'm messing around with HTML5 canvas and clipping. I am wondering how I can get the user to click on the canvas, have it clip a circle, and then repeat. So essentially, the user can click multiple times and there will be multiple clips.
I tried a couple solutions that were slightly similar to what I want but it isn't working.
Here is the clipping code:
context.save();
context.beginPath();
context.arc(mouseX,mouseY,50,50,Math.PI*2,true);
context.globalCompositeOperation = 'destination-out';
context.clip();
context.closePath();
var img = new Image();
img.src = canvasSnowflake.toDataURL();
context.drawImage(canvasSnowflake, 0, 0);
context.restore();
you can view the entire thing in action here: http://jsfiddle.net/cnbishop/8FzuB/. right now you can click one time and the clip works, but you can get a new clip if you click on the canvas again. Is this even possible?
Everytime the user clips you'll need to save this action somehow in JS. Next time the user clicks, you retrieve the past clipping, apply it and then apply the new clip action.
Basically, you need to reapply all the clipping actions in the history in the same order as they were executed as Canvas is unable to "remember" its previous rendering.
Did I interpret your question correctly?