Flash drawing line overlapping check - actionscript-3

I have an application where user have to draw a line on the canvas without overlapping it. Is there a way to test the overlapping? I have googled already but found result with circles and rectangle overlapping. My case is different. Here user will draw lines on canvas without overlap the line itself. May be I am missing something so any guidance is appreciated. Thanks

I take it you mean the user draws a line with some sort of pen tool, using the mouse.
Here's what I would do:
First, hold the path of the line drawn in a BitmapData object.
var lineBitmapData:BitmapData = new BitmapData(display.width,display.height,true,0x00000000);
This creates a transparent bitmap object with the user's line on it.
On each frame (or timer event, if you use timer) do the following:
1.capture the current mouse position and put it into a Point object.
var currentMousePosition:Point = new Point(mouse.x,mouse.y);
you will also need a point representing the upper-left corner of your bitmapData.
var pt1:Point = new Point(1,1);
2.perform collision detection between the current mouse position and the lineBitmapData
var result:Boolean = lineBitmapData.hitTest(pt1, 0xFF, currentMousePosition);
the second parameter in the hitTest method is the threshhold value. Basically, this needs to be set to the minimum alpha value that you want to count as a hit.
3.check the result of the hitTest. If it's false, this means what the user is about to draw this frame does not intersect what was already drawn. In this case, you add the bit that was drawn during the last frame to the lineBitmapData.
If the hitTest returns true, however, that means the user is about to make his line intersect, so your program needs to stop the drawing (or whatever behavior you want).
if(result){
myPenTool.stopDrawing();}else{
var drawnLastFrame:BitmapData = myPenTool.drawSingleFrameLine();
lineBitmapData.draw(drawnLastFrame);}
4.Update what the user sees on the screen with the new lineBitmapData

Related

Flash Games: Make a world continuous, circular

I am writing now a flash game and I run into a an issue. I have a map for the game which is defined as a 2-D array, where each element represents a component of the map. The player is always in the center of the map.
The problem is when the player reaches one end of the map. Now it is empty space. I want that the player instead of seeing the empty space, to see another end of the map and in this way, the map will loo like it goes around.
So for example if the player goes to right he will eventually start seeing the the left side of the map and the world will look continuous.
Does anyone knows how to implement this functionality?
You could make the array 2 times and put the first one behind the second one again and than the second one behind the first etc etc..
It's done here with 2 pictures, just use the arrays instead:
//The speed of the scroll movement.
var scrollSpeed:uint = 2;
//This adds two instances of the movie clip onto the stage.
var s1:ScrollBg = new ScrollBg();
var s2:ScrollBg = new ScrollBg();
addChild(s1);
addChild(s2);
//This positions the second movieclip next to the first one.
s1.x = 0;
s2.x = s1.width;
//Adds an event listener to the stage.
stage.addEventListener(Event.ENTER_FRAME, moveScroll);
//This function moves both the images to left. If the first and second
//images goes pass the left stage boundary then it gets moved to
//the other side of the stage.
function moveScroll(e:Event):void{
s1.x -= scrollSpeed;
s2.x -= scrollSpeed;
if(s1.x < -s1.width){
s1.x = s1.width;
}else if(s2.x < -s2.width){
s2.x = s2.width;
}
}
You simply check if your player is about to get off the "right" or "left" edge of the map, and position him at the other edge. To draw a circular map, you can use the following technique: if you are about to draw a column of a number that exceeds the map's width, decrease that number by width and draw the column at resultant index; and if you are about to draw a column at index below zero, add width and draw the column at resultant index. If you are in troubles of making a hitcheck at continuous map's borders, you can employ the same trick to find neighbors. (The "circular array" is a pretty basic algorithmic problem, and is resolved in many ways already)
You have a few options here. You can do the pac-man style of just making your character pop up on the other side of the screen, but that would require you to abandon the cool bit of the character being in the middle at all times.
On to the real suggestions:
If you're not implementing your array as one solid object (i.e. making it draw individual collumns/rows at a time) then this is a no-brainer. Just have a function that returns the index of the next collumn/row, within certain bounds. Like, if your array is 40 elements wide, when it tries to draw element 41, subtract the size of the array, and make it draw element 1 instead.
If your array is one solid object (like if you drew it onto a stage object and are just manipulating that) and it's not very big, you could probably get away with drawing a total of four of them, and just having a new one cover up any whitespace that's about to appear. Like, as you approach the right edge of the first array, the second array moves to the right of it for a lawless transition.
If your array is a solid object and is very big, perhaps you could make eight buffer objects (one per edge and one per corner) that hold approximately half a screen's worth of the array. That way as you approach the right edge, you see the left edge, but then when you cross into the buffer zone, you could teleport the player to the corresponding position on the left of the array, which has the buffer for the right size. To the player, nothing has changed, but now they're on the other side of the world.

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.

AS3 How to set cursor property move

I am unable to set my flash cursor from auto to move, any help ?
private function itemCursorMove(e:MouseEvent){
Mouse.cursor = "move";
e.currentTarget.addEventListener(MouseEvent.MOUSE_OUT,itemCursorAuto);
}
You have to manually registerCursor() a "move" cursor. In order to register a new mouse cursor, you need to have:
A vector of bitmap images that contain cursor shapes. Can have a length of 1, with a single shape. Maximal bitmap size is 32x32.
A defined hotspot (the point which actually interacts with environment), you manually define it basing on your images.
A combined MouseCursorData object, filled with this data. Description here. You just create it, fill its properties and pass it to...
A Mouse.registerCursor() call. The manual is here. In short, you provide it a String that will be the name of the cursor, and a prepared object.
This is only needed to be done once at initialization. An example:
var mcd:MouseCursorData=new MouseCursorData();
mcd.data=Vector.<BitmapData>([new MyCursorImage().bitmapData]); // a single image
// MyCursorImage is an asset of type Bitmap
mcd.hotSpot=new Point(); // top left corner is action point
Mouse.registerCursor("move",mcd);

AS3 MovieClip getRealBounds

As you well know in as3 we have a getBounds() method which returns the exact dimension and coordinates of the movieclip in the DisplayObject container we want.
Fact is that these data are calculated based on the graphics in their state in the MC at the frame it is while getBounds() is called.
What I want is the REAL bounds rectangle, that is the larger rectangle that the WHOLE animated movieclip will take in its container.
I thought of two ways:
1 - a flash built-in method that I don't know
2 - going through every frame always getting the bounds and finally returning the biggest (but what if it's a long animation? should I wait for it to play completely before I can get what I want?)
I hope I've been clear. If you need examples, let me know!
You can iterate through each frame without having to wait for the animation to play:
Let's say your clip is called bob:
var lifetimeBounds:Rectangle = new Rectangle();
bob.gotoAndStop(1);
for(var i:int=1;i<=bob.totalFrames;i++){
lifetimeBounds.width = Math.max(lifetimeBounds.width, bob.width);
lifetimeBounds.height = Math.max(lifetimeBounds.height, bob.height);
lifetimeBounds.x = Math.min(lifetimeBounds.x, bob.x);
lifetimeBounds.y = Math.min(lifetimeBounds.y, bob.y);
bob.nextFrame();
}
bob.gotoAndStop(1); //reset bob back to the beginning
It's more CPU taxing (so I'd recommend not using it if the above works for your situation), but you could also use getBounds() in the example above and compare the returned rectangle against the lifetimeBounds rectangle:
var tempRect:Rectangle;
var lifetimeBounds:Rectangle = new Rectangle();
bob.gotoAndStop(1);
for(var i:int=1;i<=bob.totalFrames;i++){
tmpRect = bob.getBounds(this);
lifetimeBounds.width = Math.max(lifetimeBounds.width, tempRect.width);
lifetimeBounds.height = Math.max(lifetimeBounds.height, tempRect.height);
lifetimeBounds.x = Math.min(lifetimeBounds.x, tempRect.x);
lifetimeBounds.y = Math.min(lifetimeBounds.y, tempRect.y);
bob.nextFrame();
}
I had this issue when converting animations to bitmapData frames, as I wanted all the resulting frames to be a uniform size and match the largest frame dimensions.
I basically had to loop through the animation 1 frame at a time and compare the bounding box to the current largest dimensions. I too thought it was a less than an ideal solution, but it worked.
So #2 is your best bet, as there is no flash built in method that provides what you seek.

Deleting a shape via code

Pretty basic question here, but its still got me a little confused..
I have an object(navigation menu bar) that I want to change the colors on with code, so in an updateColor function, I get the bounds of the object (which is a drawing shape contained in a movieclip) and redraw a new shape on top of it with the new color, but I've noticed that the last shape still exists behind this redraw.
I tried using obj.graphics.clear(); before the redraw but that didn't get rid of the original shape. Is there another command that I'm overlooking?
Unless you drew the object you wish to remove within the same graphics object, clearing won't work. You need to remove the DisplayObject.
Depending on the number of children you can do:
obj.removeChildAt(0);
This also removes movieclips / buttons you placed on the stage manually.
If you have a reference to the DisplayObject you wish to remove you can simply do
obj.removeChild(backgroundClip);
Note that you can also change the color of a DisplayObject directly:
import flash.geom.ColorTransform;
...
public var test:MovieClip; //instance on stage
...
var cf:ColorTransform = test.transform.colorTransform;
cf.color = 0xff0000;
test.transform.colorTransform = cf;
while(this.numChildren)
{
this.removeChildAt(0);
}
Will clear child object on this MovieClip,
if it's clearing too much, then put the shape drawing in a subclip, and clear the subclip.