Smooth Drawing

This method creates beziers using the points drawn.

[size=1]I thought this might warrant it’s own thread, for searchers’ sake.[/size]

I’ve used two methods. One takes every point where the distance from the previous point is 50 and the other method follows a slightly more standard procedure by taking the position of the mouse on every new frame.

1: Test
[size=1]Takes points 50 units away from each other.[/size]

import flash.geom.Point;

Stage.scaleMode = "noScale";
Stage.align = "TL";
Stage.showMenu = false;

var track:MovieClip;
var section:MovieClip;
var length:Number = 30;

var points:Array = [];
var p:Point;
var drawing:Boolean = false;

function onMouseDown() {
	points = [];
	
	drawing = true;
	section = _root.createEmptyMovieClip("_section", 2);
	section._x = _xmouse;
	section._y = _ymouse;
	section.onMouseMove = function() {
		this.clear();
		this.lineStyle(1, 0x666666);
		this.lineTo(this._xmouse, this._ymouse);
	}
	section.onMouseMove();
	
	p = new Point(_xmouse, _ymouse);
	points.push(p);
	
	_root.lineStyle(1, 0xCCCCCC);
	_root.moveTo(_xmouse, _ymouse);
}

function onMouseUp() {
	points.push(new Point(_xmouse, _ymouse));
	_root.lineTo(_xmouse, _ymouse);
	
	drawing = false;
	section.removeMovieClip();
	
	if (!track) {
		track = _root.createEmptyMovieClip("_track", 1);
	}
	
	var p1:Point, p2:Point, p3:Point, mid1:Point, mid2:Point;
	var p1:Point = linearBezierPoint([points[0], points[1]], 0.5);
	
	track.lineStyle(0, 0x000000);
	track.moveTo(points[0].x, points[0].y);
	track.lineTo(p1.x, p1.y);
	
	for (var i:Number=0; i<points.length-2; i++) {
		p1 = points*;
		p2 = points[i+1];
		p3 = points[i+2];
		mid1 = linearBezierPoint([p1, p2], 0.5);
		mid2 = linearBezierPoint([p2, p3], 0.5);
		track.bezier([mid1, p2, mid2], 20);
	}
	
	track.lineTo(p3.x, p3.y);
}

function onMouseMove() {
	if (!drawing) return;
	
	var dx:Number = _xmouse - p.x;
	var dy:Number = _ymouse - p.y;
	var d:Number = Math.sqrt(dx*dx+dy*dy);
	
	if (d >= length) {
		section._x = _xmouse;
		section._y = _ymouse;
		section.onMouseMove();
		
		p = new Point(_xmouse, _ymouse);
		points.push(p);
		
		_root.lineTo(_xmouse, _ymouse);
	}
}

MovieClip.prototype.linearBezierPoint = function(p:Array, t:Number):Point {
    if (t < 0 || t > 1 || p.length != 2) return null;
   
    return new Point(
        p[0].x+(p[1].x-p[0].x)*t,
        p[0].y+(p[1].y-p[0].y)*t
    );
};

MovieClip.prototype.quadraticBezierPoint = function(p:Array, t:Number):Point {
    if (t < 0 || t > 1 || p.length != 3) return null;
   
    var ax:Number, bx:Number;
    bx = 2*(p[1].x-p[0].x);
    ax = p[2].x - p[0].x - bx;
   
    var ay:Number, by:Number;
    by = 2*(p[1].y - p[0].y);
    ay = p[2].y - p[0].y - by;
   
    var t2:Number = t*t;
   
    return new Point(
        ax*t2 + bx*t + p[0].x,
        ay*t2 + by*t + p[0].y
    );
};

MovieClip.prototype.bezier = function (p:Array, segments:Number) {
    if (segments < 1) return;
   
    var func:Function;
    if (p.length < 2) {
        return;
    } else if (p.length == 2) {
        func = this.linearBezierPoint;
    } else if (p.length == 3) {
        func = this.quadraticBezierPoint;
    } else if (p.length == 4) {
        func = this.cubicBezierPoint;
    } else {
        return;
    }
   
    var dt:Number = 1/segments;
    var s:Point = func(p, 0);
    this.moveTo(s.x, s.y);
   
    for (var i:Number=1; i<=segments; i++) {
        s = func(p, i*dt);
        this.lineTo(s.x, s.y);
    }
}

function onKeyDown() {
	if (Key.getCode() == Key.SPACE) {
		_root.clear();
		track.clear();
		_root.lineStyle(1, 0xCCCCCC);
		track.lineStyle(0, 0x000000);
	}
}
Key.addListener(this);

2: Test
[size=1]A slightly more conventional method, takes points where the mouse on every new frame.[/size]

import flash.geom.Point;

Stage.scaleMode = "noScale";
Stage.align = "TL";
Stage.showMenu = false;

var track:MovieClip;
var section:MovieClip;
var length:Number = 50;

var points:Array = [];
var p:Point;
var drawing:Boolean = false;

function onMouseDown() {
	points = [];
	drawing = true;
	
	p = new Point(_xmouse, _ymouse);
	points.push(p);
	
	_root.lineStyle(1, 0xCCCCCC);
	_root.moveTo(_xmouse, _ymouse);
}

function onMouseUp() {
	points.push(new Point(_xmouse, _ymouse));
	_root.lineTo(_xmouse, _ymouse);
	
	drawing = false;
	section.removeMovieClip();
	
	if (!track) {
		track = _root.createEmptyMovieClip("_track", 1);
	}
	
	var p1:Point, p2:Point, p3:Point, mid1:Point, mid2:Point;
	var p1:Point = linearBezierPoint([points[0], points[1]], 0.5);
	
	track.lineStyle(0, 0x000000);
	track.moveTo(points[0].x, points[0].y);
	track.lineTo(p1.x, p1.y);
	
	for (var i:Number=0; i<points.length-2; i++) {
		p1 = points*;
		p2 = points[i+1];
		p3 = points[i+2];
		mid1 = linearBezierPoint([p1, p2], 0.5);
		mid2 = linearBezierPoint([p2, p3], 0.5);
		track.bezier([mid1, p2, mid2], 20);
	}
	
	track.lineTo(p3.x, p3.y);
}

function onEnterFrame() {
	if (!drawing) return;
	
	p = new Point(_xmouse, _ymouse);
	points.push(p);
	
	_root.lineTo(_xmouse, _ymouse);
}

MovieClip.prototype.linearBezierPoint = function(p:Array, t:Number):Point {
    if (t < 0 || t > 1 || p.length != 2) return null;
   
    return new Point(
        p[0].x+(p[1].x-p[0].x)*t,
        p[0].y+(p[1].y-p[0].y)*t
    );
};

MovieClip.prototype.quadraticBezierPoint = function(p:Array, t:Number):Point {
    if (t < 0 || t > 1 || p.length != 3) return null;
   
    var ax:Number, bx:Number;
    bx = 2*(p[1].x-p[0].x);
    ax = p[2].x - p[0].x - bx;
   
    var ay:Number, by:Number;
    by = 2*(p[1].y - p[0].y);
    ay = p[2].y - p[0].y - by;
   
    var t2:Number = t*t;
   
    return new Point(
        ax*t2 + bx*t + p[0].x,
        ay*t2 + by*t + p[0].y
    );
};

MovieClip.prototype.bezier = function (p:Array, segments:Number) {
    if (segments < 1) return;
   
    var func:Function;
    if (p.length < 2) {
        return;
    } else if (p.length == 2) {
        func = this.linearBezierPoint;
    } else if (p.length == 3) {
        func = this.quadraticBezierPoint;
    } else if (p.length == 4) {
        func = this.cubicBezierPoint;
    } else {
        return;
    }
   
    var dt:Number = 1/segments;
    var s:Point = func(p, 0);
    this.moveTo(s.x, s.y);
   
    for (var i:Number=1; i<=segments; i++) {
        s = func(p, i*dt);
        this.lineTo(s.x, s.y);
    }
}

function onKeyDown() {
	if (Key.getCode() == Key.SPACE) {
		_root.clear();
		track.clear();
		_root.lineStyle(1, 0xCCCCCC);
		track.lineStyle(0, 0x000000);
	}
}
Key.addListener(this);

Enjoy,
Hope this helps somebody :thumb: