Making a Line Tool? ie point to point

Ok, well after reading the various drawing api stuff I can create a drawing board like the tutorial which works like a paint brush, BUT how do I make it work like a line tool? IE when the user clicks from one point to another, or holds shift it draws a perfect straight line?

Im baffled, Ive tried to fiddle with this code, but Im just not quietb there yet. Any ideas??


_root.createEmptyMovieClip("line",1);

_root.onMouseDown = function(){
	line.moveTo(_xmouse,_ymouse);
	line.lineStyle(2,0x000000,100);
	this.onMouseMove = function(){
		line.lineTo(_xmouse,_ymouse);
		updateAfterEvent();
	}
}
_root.onMouseUp = function(){
	this.onMouseMove = null;
}

A start:

_root.createEmptyMovieClip("line",1);

_root.onMouseDown = function(){
	line.moveTo(_xmouse,_ymouse);
	oldY=_ymouse;
	line.lineStyle(2,0x000000,100);
}
_root.onMouseUp = function(){
      if (Key.isDown(Key.SHIFT){
	line.lineTo(_xmouse,oldY);
      }
}

Version beta 1.0, as I said. Is it something like that that you want?

Thanks, yeah this is close, quiet similiar to what Ive been working on. But I want it so that the point is visible. Ie when the user clicks they see the anchor point, and then as they drag the mouse the line drags from the anchor point until they let go whereupon it draws the line from the original anchor point to where the point (_xmouse, _ymouse) the user realsed the mouse button. Make sense? :slight_smile:

Alright, I really got interested in this and tried experimenting on my own… here is what I have so far…

i = 0;
MovieClip.prototype.buildPoint = function() {
	this.lineStyle(1, 0x000000, 100);
	this.beginFill(0xE6E6E6, 100);
	this.moveTo(-3, -3);
	this.lineTo(3, -3);
	this.lineTo(3, 3);
	this.lineTo(-3, 3);
	this.lineTo(-3, -3);
};
_root.createEmptyMovieClip("line", -4);
_root.createEmptyMovieClip("tempLine", -3);
_root.createEmptyMovieClip("point1", -2);
point1.buildPoint();
_root.createEmptyMovieClip("point2", -1);
point2.buildPoint();
point1._visible = point2._visible=false;
_root.onMouseDown = function() {
	i++;
	line.moveTo(_xmouse, _ymouse);
	line.lineStyle(2, 0x000000, 100);
	xPos = _xmouse;
	yPos = _ymouse;
	point1._x = point2._x=xPos;
	point1._y = point2._y=yPos;
	point1._visible = true;
	point2._visible = true;
	this.onMouseMove = function() {
		tempLine.clear();
		tempLine.lineStyle(2, 0xE6E6E6, 50);
		tempLine.moveTo(xPos, yPos);
		if (Key.isDown(Key.SHIFT)) {
			if (_ymouse<=yPos-100 || _ymouse>=yPos+100) {
				point2._x = xPos;
				point2._y = _ymouse;
				tempLine.lineTo(xPos, _ymouse);
			} else {
				point2._x = _xmouse;
				point2._y = yPos;
				tempLine.lineTo(_xmouse, yPos);
			}
		} else {
			point2._x = _xmouse;
			point2._y = _ymouse;
			tempLine.lineTo(_xmouse, _ymouse);
		}
	};
};
_root.onMouseUp = function() {
	tempLine.clear();
	delete this.onMouseMove;
	point1._visible = point2._visible=false;
	if (Key.isDown(Key.SHIFT)) {
		if (_ymouse<=yPos-100 || _ymouse>=yPos+100) {
			line.lineTo(xPos, _ymouse);
		} else {
			line.lineTo(_xmouse, yPos);
		}
	} else {
		line.lineTo(_xmouse, _ymouse);
	}
	if (i>=10) {
		i = 0;
	}
};

Remember, I was just experimenting, so feel free to do whatever you want with the above code. If you wish me to explain it, I will :slight_smile: And as for Ilyas and any other AS gods on this forum… I am pretty sure my code isn’t optimized, but I am sooo not up to that right now.

Note: It works with and without using SHIFT, and you can draw straight lines vertically and horizontally. This was fun :slight_smile:

Wow! Nice work lostinbeta :D!!! Extra nice touch with the square on the anchor point, I hadnt even thought of that.

Hmm if you have a bit of time could you explain it to me…:slight_smile:

Also I keep seeing more use of the prototype. I might ask you then, there was another post, i was having troubles building a prototype and using it to initialise attached Mc’s. I could use my prototype to give my attached clip mouseUp and mousePress functionality, but I couldnt build an onLoad function to load textvars (via LOadVars()) to populate the textfields within the attached mc. In short could you give me a hint on how do do this?

Thanks :stuck_out_tongue:

kudos, lost. that is some impressive work!
I second mindfriction’s request for a peek into yer process(-:

fun stuff.

jcs

Ye i gotta admit that is pretty impressive , Give us a tutorial on it!!! wooohooo lol :sigh: . I would even recommend that it added to best of kirupa :smiley:

I will gladly explain myself. I actually did the first time, but on sending the forum went down and I wasn’t about to retype it all over…lol. But I can do it now :slight_smile:

First, I changed my code a bit, using functions for everything. Here is my new code. I will explain it bit by bit.

i = 0;
MovieClip.prototype.buildPoint = function(halfWidth) {
	this.lineStyle(1, 0x000000, 200);
	this.beginFill(0xE6E6E6, 100);
	this.moveTo(-halfWidth, -halfWidth);
	this.lineTo(halfWidth, -halfWidth);
	this.lineTo(halfWidth, halfWidth);
	this.lineTo(-halfWidth, halfWidth);
	this.lineTo(-halfWidth, -halfWidth);
};
function drawProcess() {
	i++;
	xPos = _xmouse;
	yPos = _ymouse;
	point1._x = point2._x=xPos;
	point1._y = point2._y=yPos;
	point1._visible = point2._visible=true;
	line.moveTo(xPos, yPos);
	this.onMouseMove = function() {
		tempLine.clear();
		tempLine.lineStyle(2, 0xE6E6E6, 50);
		tempLine.moveTo(xPos, yPos);
		if (Key.isDown(Key.SHIFT)) {
			if (_ymouse<=yPos-100 || _ymouse>=yPos+100) {
				point2._x = xPos;
				point2._y = _ymouse;
				tempLine.lineTo(xPos, _ymouse);
			} else {
				point2._x = _xmouse;
				point2._y = yPos;
				tempLine.lineTo(_xmouse, yPos);
			}
		} else {
			point2._x = _xmouse;
			point2._y = _ymouse;
			tempLine.lineTo(_xmouse, _ymouse);
		}
	};
}
function drawFinalLine() {
	tempLine.clear();
	delete this.onMouseMove;
	point1._visible = point2._visible=false;
	line.lineStyle(.25, 0x000000, 100);
	if (Key.isDown(Key.SHIFT)) {
		if (_ymouse<=yPos-100 || _ymouse>=yPos+100) {
			line.lineTo(xPos, _ymouse);
		} else {
			line.lineTo(_xmouse, yPos);
		}
	} else {
		line.lineTo(_xmouse, _ymouse);
	}
	if (i>=4) {
		i = 0;
	}
}
function clearMe() {
	if (Key.isDown(Key.DELETEKEY)) {
		line.clear();
	}
}
_root.createEmptyMovieClip("line", 1);
_root.createEmptyMovieClip("tempLine", 2);
_root.createEmptyMovieClip("point1", 3).buildPoint(3);
_root.createEmptyMovieClip("point2", 4).buildPoint(3);
point1._visible = point2._visible=false;
_root.onMouseDown = drawProcess;
_root.onMouseUp = drawFinalLine;
_root.onEnterFrame = clearMe;

Alright, let’s start with “i”.

i = 0;

This is just a variable. We will later increment the variables number so that each clip and line drawn will be on different levels without overwriting eachother (since only one object can be on a level at a time).

Next up is the prototype I used to build the points. I used a prototype here because of it’s ability to use “this” as a locator, and since you can do that you can call the function directly to a movie clip symbol and have it effect only that movie clip symbol without having to retype all of that code. I probably am not explaining myself right here so check out Ilyas’ great prototypes tutorial, it is where I learned how to use prototypes. TUTORIAL HERE

MovieClip.prototype.buildPoint = function(halfWidth) {
	this.lineStyle(1, 0x000000, 200);
	this.beginFill(0xE6E6E6, 100);
	this.moveTo(-halfWidth, -halfWidth);
	this.lineTo(halfWidth, -halfWidth);
	this.lineTo(halfWidth, halfWidth);
	this.lineTo(-halfWidth, halfWidth);
	this.lineTo(-halfWidth, -halfWidth);
};

As you can tell, this prototype changed since the last time. I added a parameter to the function called halfWidth. What this does is when you call the prototype you will have to define that parameters number, which would be half of the width you want your end point to be. The prototype then accomidates this parameter and using the drawing API to draw the square to the correct size. I think the code inside is pretty self explanitory if you already know the drawing API (which you did the tutorials, so you know).

Now let us move on. Here we come up to the drawProcess function. This is the function that creates the end points and draws the grey line while you are in the process of creating your line.

function drawProcess() {
	i++;
	xPos = _xmouse;
	yPos = _ymouse;
	point1._x = point2._x=xPos;
	point1._y = point2._y=yPos;
	point1._visible = point2._visible=true;
	line.moveTo(xPos, yPos);
	this.onMouseMove = function() {
		tempLine.clear();
		tempLine.lineStyle(2, 0xE6E6E6, 50);
		tempLine.moveTo(xPos, yPos);
		if (Key.isDown(Key.SHIFT)) {
			if (_ymouse<=yPos-100 || _ymouse>=yPos+100) {
				point2._x = xPos;
				point2._y = _ymouse;
				tempLine.lineTo(xPos, _ymouse);
			} else {
				point2._x = _xmouse;
				point2._y = yPos;
				tempLine.lineTo(_xmouse, yPos);
			}
		} else {
			point2._x = _xmouse;
			point2._y = _ymouse;
			tempLine.lineTo(_xmouse, _ymouse);
		}
	};
}

Wow… much bigger now :wink: The first thing it does is increments “i” by 1. i++ is the same as saying i = i+1.

	xPos = _xmouse;
	yPos = _ymouse;

Since we will later be calling this function onMouseDown the xPos and yPos variables will be the _xmouse and _ymouse positions at the time of pressing your mouse button down. This will later set the anchor point 1 position and be used in drawing your line.

	point1._x = point2._x=xPos;
	point1._y = point2._y=yPos;
	point1._visible = point2._visible=true;

Alright here it may loko a bit strange because I have so many equal signs…lol. Well what I did here was combined variables to make my code shorter. When two items equal the same exact thing you can string them along as I did above. In this cause point1._x and point2._x will both be equal to the xPos when the mouse is down. Same goes for the point1._y and point2._y. This also then makes point1 and point2 visible (as we make them invisible when not creating a line we will need to make them visible while drawing the line).

line.moveTo(xPos, yPos);

Moves the line clip to the xPos and yPos which is where the anchor point1 will be and will be the start of the line.

this.onMouseMove = function() {
		tempLine.clear();
		tempLine.lineStyle(2, 0xE6E6E6, 50);
		tempLine.moveTo(xPos, yPos);
		if (Key.isDown(Key.SHIFT)) {
			if (_ymouse<=yPos-100 || _ymouse>=yPos+100) {
				point2._x = xPos;
				point2._y = _ymouse;
				tempLine.lineTo(xPos, _ymouse);
			} else {
				point2._x = _xmouse;
				point2._y = yPos;
				tempLine.lineTo(_xmouse, yPos);
			}
		} else {
			point2._x = _xmouse;
			point2._y = _ymouse;
			tempLine.lineTo(_xmouse, _ymouse);
		}
	};

This following code allows the grey line and points to work. It targets the clip tempLine which we will create later and will be the clip to hold grey line. You will see it first uses clear(). I did this because if we didn’t, then the line would always be repeated making for a real big sloppy ugly mess. Remove it and see what I mean. Then we define the lineStyle and move the clip to where point1 is, which is the start of our grey line.
The if statement is what allows us to do the straight line method or not. As you see the first if is if the key that is down is the shift key, then inside that if statement there is another if/else statement. This embedded if/else statement is to check for vertical or horizontal straight line drawing. The if statement first checks if the _ymouse is outside a 100px radius (100px up or 100px down) of the original yPos. If that is true, the line is moved only vertically, but if that is false it moves onto the else statement to which is moves the line only horizontally. After mentioned the xPos and yPos so much already I am pretty sure the code in those statements is self explanitory. Now after that you will see another else statement that belongs to the main if statement. This says that if shift is NOT held down, then to just move the line to where the current mouse position is.
Wow, I hope I made sense. Now it is time to talk about the function that actually draws our final line!

function drawFinalLine() {
	tempLine.clear();
	delete this.onMouseMove;
	point1._visible = point2._visible=false;
	line.lineStyle(.25, 0x000000, 100);
	if (Key.isDown(Key.SHIFT)) {
		if (_ymouse<=yPos-100 || _ymouse>=yPos+100) {
			line.lineTo(xPos, _ymouse);
		} else {
			line.lineTo(_xmouse, yPos);
		}
	} else {
		line.lineTo(_xmouse, _ymouse);
	}
	if (i>=4) {
		i = 0;
	}
}

It first uses clear() to clear the grey line from being on the stage. Why have it there if you don’t need it right? It then deletes the dynamic event hander for the onMouseMove. This is important otherwise your grey line will still continue to draw, and it will still continue to follow your mouse everywhere. We don’t want that of course. Alright, so that grey line is all taken care of, we then make the points invisible by setting their _visible property back to false.
The if statements in here are the same as in the previous function, but the only difference is that instead of moving the line it actually draws the line instead.
But wait… why do I make “i” go back to 0? Simple, if we don’t reset “i”, then your levels will keep increasing and increasing. Why keep doing that when this only uses for levels so we can just use the same 4 over and over. It seems more efficient to me, but I don’t know, I am not a very efficient coder :-
Well that is it for that function. Time for the deleteMe() function.

function clearMe() {
	if (Key.isDown(Key.DELETEKEY)) {
		line.clear();
	}
}

Simple, when the delete key is pressed, clear the lines! You don’t need this, but I was having a lot of fun messing with this and testing new things with it, when the stage would get too cluttered I hated closing and retesting it, so I just created a clear function.

_root.createEmptyMovieClip("line", 1);
_root.createEmptyMovieClip("tempLine", 2);
_root.createEmptyMovieClip("point1", 3).buildPoint(3);
_root.createEmptyMovieClip("point2", 4).buildPoint(3);
point1._visible = point2._visible=false;
_root.onMouseDown = drawProcess;
_root.onMouseUp = drawFinalLine;
_root.onEnterFrame = clearMe;

It creates 4 empty movie clips. You will notice their levels are the first 4 levels, which is all I plan to use for this.
You will also notice that the creation of point1 and point2 also include the buildPoint function. This is a weird way of writing it, but it saves us a line rather than creating a new line that say point1.buildPoint(3) we can just attach it to the actual creation of the clip. It builds a point with a halfWidth of 3 (making our point 6px wide total).
Then it sets point1 and point2 to be invisible when the movie first starts so you don’t see them in the upper left corner where they are originally created (when an position is undefined it defaults to (0,0)).
We then proceed to add dynamic event handlers. onMouse down we call the drawProcess which creates the faux line we originally see, then onMouseUp we call the drawFinalLine function which actually draws the line and remove the faux line, then onEnterFrame we call the clearMe function which contanstly checks if the delete key is being pressed and if so it clears the stage of the lines we drew.

You can read up on dynamic event handlers (another great Ilyas tutorial that taught me)… TUTORIAL HERE

Whew… Sorry I know there is a character limit in these posts so I tried to make it as short and to the point as possible. If their is any part you don’t understand please just ask and I will be able to go further into detail about it.

I am just waiting for Ilyas or Senocular to come along and tell me I wasted my time and then post like 6 lines of code to do the same thing…LOL :stuck_out_tongue:

Thats real swell of ya lostinbeta. My learning curve just got higher :). And I agree, I think you could submit this as a tutorial for full recoginiton of your great effort :stuck_out_tongue: I must say Im not fully confident with everything about the code but I have a rough idea whats going on. Its a pretty organised piece of code. Well Im going to mess round with it and maybe I’ll send you a link/ attach the movie I used it in.

Hahah yeah Im guessing Senocular, or ilyaslamasse will be checking this thread out, I might msn senoc about it :stuck_out_tongue:

Well if there are any parts of the code you don’t understand just let me know, I will try and go into further detail of it. As I stated before, I had to keep it short and sweet because there is a limit to how much you can type in a reply, but if I dedicate the explantion to just one part I can probably go deeper into how it works.

Umm one question, you talk about using ‘i’ to keep each line and clip on a different level, but I cant see where you set any line or clip to level ‘i’. Could you explain that a bit more clearly? Thanks

Certainly, I can explain.

i = idiot… yep, where “i” is actually me.

Stupid me forgot that with my reworked method I didn’t have any use for I but I didn’t think to look over like that…LOL. My original version used “i” (the one I made before I posted my progress so far). Thing is, I changed it around so I wouldn’t need “i”, but completely forgot to remove it from the script :crazy:

So when I was explaning I knew why “i” was there in the first place, so it just dawned on me to state what it was for and it didn’t even hit me that I no longer needed “i” in this script.

Good Catch (-:

MovieClip.prototype.buildPoint = function(halfWidth) {
	this.lineStyle(1, 0x000000, 200);
	this.beginFill(0xE6E6E6, 100);
	this.moveTo(-halfWidth, -halfWidth);
	this.lineTo(halfWidth, -halfWidth);
	this.lineTo(halfWidth, halfWidth);
	this.lineTo(-halfWidth, halfWidth);
	this.lineTo(-halfWidth, -halfWidth);
};
function drawProcess() {
	xPos = _xmouse;
	yPos = _ymouse;
	point1._x = point2._x=xPos;
	point1._y = point2._y=yPos;
	point1._visible = point2._visible=true;
	line.moveTo(xPos, yPos);
	this.onMouseMove = function() {
		tempLine.clear();
		tempLine.lineStyle(2, 0xE6E6E6, 50);
		tempLine.moveTo(xPos, yPos);
		if (Key.isDown(Key.SHIFT)) {
			if (_ymouse<=yPos-100 || _ymouse>=yPos+100) {
				point2._x = xPos;
				point2._y = _ymouse;
				tempLine.lineTo(xPos, _ymouse);
			} else {
				point2._x = _xmouse;
				point2._y = yPos;
				tempLine.lineTo(_xmouse, yPos);
			}
		} else {
			point2._x = _xmouse;
			point2._y = _ymouse;
			tempLine.lineTo(_xmouse, _ymouse);
		}
	};
}
function drawFinalLine() {
	tempLine.clear();
	delete this.onMouseMove;
	point1._visible = point2._visible=false;
	line.lineStyle(.25, 0x000000, 100);
	if (Key.isDown(Key.SHIFT)) {
		if (_ymouse<=yPos-100 || _ymouse>=yPos+100) {
			line.lineTo(xPos, _ymouse);
		} else {
			line.lineTo(_xmouse, yPos);
		}
	} else {
		line.lineTo(_xmouse, _ymouse);
	}
}
function clearMe() {
	if (Key.isDown(Key.DELETEKEY)) {
		line.clear();
	}
}
_root.createEmptyMovieClip("line", 1);
_root.createEmptyMovieClip("tempLine", 2);
_root.createEmptyMovieClip("point1", 3).buildPoint(3);
_root.createEmptyMovieClip("point2", 4).buildPoint(3);
point1._visible = point2._visible=false;
_root.onMouseDown = drawProcess;
_root.onMouseUp = drawFinalLine;
_root.onEnterFrame = clearMe;

^^removed all traces of that “i”… 'DOH.

LOL, I was getting worried, it only just clicked that ‘i’ muist have been old code :stuck_out_tongue:

Well it goes with my previous statement in the description that “I am not an efficient coder”…lol. I proved myself right there.

I try to be as efficient as possible, but my mind thinks in complicated ways so it is hard :crazy:

Hmm you seem to be on a role, heh :P,

Take a look at the attachment, Ive been through the dynamic events link in kirupa.

If yoiu’ve opened my attachment you’’ see when you run the movie you can drag a circle onto the ‘canvas’ of the stage, which is all good. BUT when you try to drag the circle on the stage it duplicates the circle again and again, which isnt what i would like. Im guessing there is a way to change the onPress event for the mc, so when its on the canvas all you can do is drag it and it wont duplicate itself… Anyway see the attachment and yuo’ll understand

Looks good :slight_smile: And 6 lines seem a bit short to me :stuck_out_tongue: Maybe Sen has an idea… :evil:

Aaaaah BRAIN CLICKS :sigh:

I think Im finally getting the idea! :stuck_out_tongue:

Check out my new revised version, only thing I have to work on now is to make sure the user can only drag the circle inside the canvas. Could easily mask it i guess, but suppose I could make 'draggable area" boundry. scrathes head :ninja:

When Im finished I might try and put together a flash “doodle board”

Ilyas: Ok Ok, then 15 lines :stuck_out_tongue:

Mindfriction: Ok, I reworked your code a bit… I completely got rid of the controller clip and put all the actions on a frame. That is what makes dynamic event handlers so great :slight_smile: I also took it upon myself to add a swapDepths() feature so that when you click on the objects on the stage that you drag and drop they will be pulled to the top above all the other clips.

You can check the .fla file to see what I did.