ASP Classic with ASPX Image Resize into Access Database
Here’s a short routine using aspx to upload an image , resize it in memory then stick it into an access database. The aspx page is is in an iframe and the images are displayed on the classic index.asp parent page.
The problems.
I had an old classic asp form page that had dozens of fields for a real estate agent. I had to have a way to upload images then have them resized to 200 x 130 pixels in memory then insert images blob into an access database. I didn’t want to redo the entire asp form in aspx so I added an iframe and wrote some .net code to do the image resizing. Here’s some of the problems I had to solve.
- iframe ‘access denied’ when called parent page: Solved with javscript document.domain
- Refreshing the classic asp page after an aspx post of the image: Solve with .net’s RegisterStartupScript
- When displaying Blob image, browser cache file didn’t have a last modified date: Solved with addDate LastModified routine. Images cached correctly.
- LastModified header worked on localhost but not server. Solved by added semi-colon for server side code.
zip file contains the main index.asp, theImageResizer.aspx, a simple access database, getBlob.asp, connection.asp
- Change the ConnectString value in connection.asp to reflect your localhost and server database locations.
- Also ConnectionString in ImageResizer.aspx if needed.
- Change javascript document.domain=”ImageResizer.com” in ImageResizer.aspx to your domain name
Sub btnUpload_OnClick(Source As Object, e As EventArgs)
if fiUpload.HasFile then
Dim im, thumb, propertyID, url, imageID
im = System.Drawing.Image.FromStream(fiUpload.PostedFile.InputStream)
thumb = im.GetThumbnailImage(200, 130, Nothing, System.IntPtr.Zero)
Dim conn As New OleDbConnection
Dim cmd As OleDbCommand
conn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Server.MapPath("database/images.mdb") & ";"
conn.Open()
cmd = conn.CreateCommand()
propertyID=Request.QueryString("propertyID")
ImageID= drop1.SelectedItem.Text
cmd.CommandText = "UPDATE images SET " & ImageID & " = (@Image) WHERE propertyID = '" & propertyID & "';"
Dim imgByteArray() As Byte
Dim stream As New MemoryStream
thumb.Save(stream, ImageFormat.Jpeg)
imgByteArray = stream.ToArray()
stream.Close()
cmd.Parameters.AddWithValue("@Image", imgByteArray)
cmd.ExecuteNonQuery()
conn.Close()
cmd.Dispose()
conn.Dispose()
thumb.Dispose()
Dim scriptString As String = "RefreshParent()"
RegisterStartupScript("RefreshParent",scriptString)
end if
End Sub
Download Zip
Swingpants Collision Detection
I found some AS3 Colour Map collision code at a blogger that goes by the name of ‘Swingpants’ here. Swingpants found a very simple way to reflect objects off any shape. I couldn’t wait for part 2 of his code so I took part 1, all of which were in package classes and then placed every class except the ColourMap.as inline.
I removed all the extra debug code, renamed some variables to more readable (e.g. X1, Y1), and compacted the code to under 50 lines for the setup and less than 100 lines for the ColourMap code.
I was introduces to colour map hitTests by Grant Skinner’s blog called ‘PixelPerfect‘ then followed up with additionlly reading by Troy Gilbert and others. However, no one that I recall had coded any reflection code after the object hit the target.
I must stress that this example is all credited to Mr. Swingpants whom every he maybe. The following is what I observed:
Pros: Excellent and very short code for bouncing and reflecting off any style of shape.
Cons: None.
To dos: Ball can sometimes penitrate 50% of a horizonal or vertical lines depending on the angle. Maximum ball speed at 30 fps is around 50. No XY vectors for gravity as in pinball or for slope/angled hill in mini-put. Bouncing off rotation object may require the pixelperfect code.
Conclusion: I may never go back to trig, vector and physic engines again. Works perfect for me!
AS3 Bitmap folding with DrawTriangles

Flash 10 CS4 : ActionScript3 Bitmap fold, Drawtriangles, Page Flip, As3 uvtData, beginBitmapFill, drawPath.
functions: Intersection point of two lines, Point on hypotenuse, right angle point, point to line.
Example 1: Using just As3 DrawTriangles to fold a bitmap (no masking or rotation).
Example 2: A stripped down version of Bitmap Fold.
In this month’s posting I will show you how to use the uvtData paramater of drawTriangles to fold a bitmap.
I have made four small custom functions to retreive all the intersection and vertices points as follows:

PointOnHypotenuse(pt1,pt2,newpt,distance) simular to Point.interpolate but uses pixel distance, can also extend line. pt1:Point — The starting xy coordinate of the line. pt2:Point — The ending xy coordinate of the line. newpt:Object — The Object to move to location on line. distance:Number — distance form pt1 to place newpt. rightAnglePt(pt1,pt2,pt3,newpt,distance,norm) a right-angle line from pt3 on the line to distance. pt1:Object — Uses object's coordinate to start a line. pt2:Object — Uses object's coordinate to end a line. pt3:Object — A line to start from (usally pt1 or pt2 or a value from PointOnHypotenuse). newpt:Object — places newpt object right-angled from pt3. distance:Number — distance in pixels to place newpt from pt3. norm:int (default=0) — 0 for right-hand normal or 1 for left-hand normal (opposite direction). PointToLine(pt1,pt2,pt3,newpt) a right-angle line from pt3 to the line. pt1:Object — Uses object's coordinate to start a line. pt2:Object — Uses object's coordinate to end a line. pt3:Object — Uses third object's coordinate (anywhere away from pt1 and pt2). newpt:Object — The Object to place right-angled on the line from pt3. Intersection(pt1,pt2,pt3,pt4) finds the intersection point of two lines pt1:Point — The starting xy coordinate of first line. pt2:Point — The ending xy coordinate of first line. pt3:Point — The starting xy coordinate of second line. pt4:Point — The ending xy coordinate of second line.
The functions are below:
Note: to save from too much scrolling in the FLASH editor I placed this code in frame 2.
function PointOnHypotenuse(pt1:Point,pt2:Point,newpt:Object,distance:Number) {
var dx=pt2.x-pt1.x; var dy=pt2.y-pt1.y;
var LineLength=Math.sqrt(dx*dx+dy*dy);
var scale=distance/LineLength; //the width of our bitmap
newpt.x=pt1.x+dx*scale; newpt.y=pt1.y+dy*scale; //extend our slope in opposite direction.
}
function rightAnglePt(pt1:Object,pt2:Object,pt3:Object,newpt:Object,distance,norm:int=0) {
var normal:Point = new Point(pt1.x-pt2.x,pt1.y-pt2.y); normal.normalize(1);
if (norm==0) {normal.x=-normal.x;} else {normal.y=-normal.y} //rightside=0 leftside=any number.
var normal1:Point = new Point(normal.y, normal.x);
newpt.x=pt3.x+normal1.x * distance; newpt.y=pt3.y+normal1.y * distance
}
function PointToLine(pt1:Object,pt2:Object,pt3:Object,newpt:Object) {
var dx = pt2.x - pt1.x; var dy = pt2.y - pt1.y;
if (dx == 0 && dy == 0) {
newpt.x = pt1.x; newpt.y = pt1.y;
} else {
var t = ((pt3.x-pt1.x) * dx + (pt3.y-pt1.y) * dy) / (dx * dx + dy * dy);
newpt.x = pt1.x + t * dx; newpt.y = pt1.y + t * dy;
}
}
function Intersection(pt1:Point,pt2:Point,pt3:Point,pt4:Point):Point {
var a1, a2, b1, b2, c1, c2:Number; var intersection:Point=new Point();
a1=pt2.y-pt1.y; b1=pt1.x-pt2.x; c1=pt2.x*pt1.y-pt1.x*pt2.y;
a2=pt4.y-pt3.y; b2=pt3.x-pt4.x; c2=pt4.x*pt3.y-pt3.x*pt4.y;
var denominator:Number=a1*b2-a2*b1;
if(denominator == 0) {intersection.x=0; intersection.y=0; return intersection;} //infinity error.
intersection.x=(b1*c2 - b2*c1)/denominator;
intersection.y=(a2*c1 - a1*c2)/denominator;
return intersection; //line intersection of our rectangular page's edge (pt3 and pt4).
}
The next part is the code that folds the bitmap:
Note: I placed this code in frame 3 and added a stop(); command at the top of frame 3.
stop(); //do not remove stop!
var dropShadow:DropShadowFilter = new DropShadowFilter(); //shadow filter not required.
dropShadow.color = 0x000000; dropShadow.blurX = 10; dropShadow.blurY = 10;
dropShadow.angle = 215; dropShadow.alpha = 0.5; dropShadow.distance = 10;
var filtersArray:Array = new Array(dropShadow);
frontpage.filters = filtersArray; //fold shadow not required.
page.filters = filtersArray; //page shadow not required.
var mouse:Point=new Point();
var leftEdge=false; var rightEdge=false; var bottomEdge=false; var topEdge=false;
var A:Point = new Point(page.x,page.y); //topleft page
var B:Point = new Point(A.x+bmpWidth,A.y); //topright page
var C:Point = new Point(B.x,A.y+bmpHeight); //bottomright page
var D:Point = new Point(A.x,C.y); //bottomleft page
var N:Point= new Point(); //holds right-angled point of normal.
function foldpaper() { //Main Program Code.
rightEdge=false; bottomEdge=false; leftEdge=false; topEdge=false; tearoff=false;//reset.
mouse.x=mouseX; mouse.y=mouseY;
var midpt:Point = Point.interpolate(A,mouse,.5); //center point of drag line to start corner.
rightAnglePt(A,mouse,midpt,N,1,1) //get right hand normal (pt1,pt2,pt,newpt,lineLength,LR:int=0)
var AB:Point=Intersection(midpt,N,A,B); //Get page's rectangle intersection points.
var BC:Point=Intersection(midpt,N,B,C);
var CD:Point=Intersection(midpt,N,C,D);
var DA:Point=Intersection(midpt,N,D,A);
if(AB.x==0 || AB.y==0 || DA.x==0 || DA.y==0){return;} //can't intersect lines, infinity error.
if(AB.x <= A.x && DA.y <=A.y || CD.x =D.y) {tearOffImage(AB,0)} //left-side
if(AB.x >= B.x && BC.y = C.x && BC.y >=C.y) {tearOffImage(AB,1)} //right-side
if (tearoff==false) {
if(mouse.y < B.y && BC.y A.x) { //right-side top drag special case, things reverse.
node1.x=BC.x; node1.y=BC.y;
node2.x=AB.x; node2.y=AB.y;
PointOnHypotenuse(mouse,DA,node4,-bmpHeight); //missing referance point so extend slope line.
PointToLine(node4,CD,node1,node3); topEdge=true;
} else if(mouse.x < D.x && CD.x =A.x && AB.x=B.y && BC.y=D.x && CD.x=A.y && DA.y<=D.y) {node1.x=DA.x; node1.y=DA.y;}
PointToLine(mouse,AB,node2,node3); PointToLine(mouse,DA,node1,node4);
}
} //end of if tear off.
DrawTriangles(); //draw the backpage.
}
function DrawTriangles() {
var vertices:Vector.=new Vector.;
var indices:Vector.=new Vector.();
var uvtData:Vector.=new Vector.();
var drawpath:Vector. = new Vector.();
var coord:Vector. = new Vector.();
//UH length for uvtData are measured from node1 or node2 intersections to corners A or B.
var Bxn2=(B.x-node2.x)/bmpWidth; // width normalized 1-0 for uvtData.
var n1Ay=(node1.y-A.y)/bmpHeight; // height normalized 0-1 for uvtData.
var n2Ay=(node2.y-A.y)/bmpHeight; // short rightside normalized 0-1 for uvtData.
var n1Ax=(node1.x-A.x)/bmpWidth; // short bottomside normalized 0-1 for uvtData.
var Bxn1=(B.x-node1.x)/bmpWidth; // short bottomside normalized 1-0 for uvtData.
frontpage.graphics.clear();
frontpage.graphics.lineStyle(showlines,0xFF0000); //showVertices code in frame 1 for showlines.
if (tearoff) { //two triangle full rectangle. Mouse is the uvt 0,0 position.
vertices.push(mouse.x,mouse.y,node4.x,node4.y,node3.x,node3.y,node2.x,node2.y);
indices.push(0,1,3, 1,2,3); //start at mouse top-right corner going clock-wise.
uvtData.push(1,0, 1,1, 0,1, 0,0); //It's normally 0,0, 1,0, 1,1, 0,1 from top-left corner.
} else if (topEdge) { //three triangles
vertices.push(mouse.x,mouse.y,node4.x,node4.y,node3.x,node3.y,node1.x,node1.y,node2.x,node2.y);
indices.push(0,1,4, 1,3,4, 1,2,3);
uvtData.push(1,0, 1,1, 0,n1Ax, 0,n1Ay, Bxn2,0);
} else if (leftEdge) { //three triangles.
vertices.push(mouse.x,mouse.y,node1.x,node1.y,node2.x,node2.y,node4.x,node4.y,node3.x,node3.y);
indices.push(0,1,4, 1,3,4, 1,2,3);
uvtData.push(1,0, 1,n1Ay, Bxn2,n2Ay, 0,1, 0,0);
} else if (rightEdge && bottomEdge) { //three triangles.
vertices.push(mouse.x,mouse.y,node4.x,node4.y,node1.x,node1.y,node2.x,node2.y,node3.x,node3.y);
indices.push(0,1,4, 1,3,4, 1,2,3);
uvtData.push(1,0, 1,1, Bxn1,1, Bxn2,n2Ay, 0,0);
} else if (rightEdge) { //two triangles uvt clipped.
vertices.push(mouse.x,mouse.y,node1.x,node1.y,node2.x,node2.y,node3.x,node3.y);
indices.push(0,1,3, 1,2,3);
uvtData.push(1,0, 1,n1Ay, 0,n2Ay, 0,0);
} else if (bottomEdge) { //two triangles uvt clipped.
vertices.push(mouse.x,mouse.y,node4.x,node4.y,node1.x,node1.y,node2.x,node2.y);
indices.push(0,1,3, 1,2,3);
uvtData.push(1,0, 1,1, Bxn1,1, Bxn2,0);
} else { //start corner, one triangle page curl.
vertices.push(mouse.x,mouse.y,node1.x,node1.y,node2.x,node2.y);
indices.push(0,1,2);
uvtData.push(1,0, 1,n1Ay, Bxn2,0);
}
if (updateBasePage) { //update the bottom base Page once only, otherwise 90% CPU hog.
page.graphics.beginBitmapFill(bitmapData[shuffle[2]],null,false,true); //draw the stage base-page.
page.graphics.drawRect(0,0,bmpWidth,bmpHeight);
page.graphics.endFill(); updateBasePage=false;
}
if (leftEdge==false && topEdge==false && tearoff==false) { //draw the frontpage overlay.
frontpage.graphics.beginBitmapFill(bitmapData[shuffle[0]],matrix,false,true);
drawpath.push(1,2,2,2,2,2);
coord.push(node2.x,node2.y, mouse.x,mouse.y, node1.x,node1.y, D.x,D.y, C.x,C.y, B.x,B.y);
frontpage.graphics.drawPath(drawpath, coord);
frontpage.graphics.endFill();
}
frontpage.graphics.beginBitmapFill(bitmapData[shuffle[1]],null,false,true); //draw the backpage fold image.
frontpage.graphics.drawTriangles(vertices,indices,uvtData);
frontpage.graphics.endFill();
}
function tearOffImage(edge,normal) { //exceeded the page's boundaries so tear off the page.
tearoff=true; var W; var H;
if (normal==1) {W=bmpWidth; H=bmpHeight} else {W=-bmpWidth; H=-bmpHeight}
PointOnHypotenuse(mouse,edge,node2,W);
rightAnglePt(mouse,edge,node2,node3,H,1)
rightAnglePt(node2,node3,node3,node4,W,normal)
}
The final code is really the first code section I place on frame 1.
This frame sets up the stage, listeners and bitmapdata to use.
Now I’m not going to do everything for you. You need stage objects to make it work.
Secondly I’m a recession case (laid off for good) so I’m not providing the fla file.
Does anyone pay people to be do this anymore? If so, email me (Canadian with no green card).
Here’s a really big hint:
- a checkbox instance named ‘CheckBox1′ and another named ‘CheckBox2′.
- place five images page1.jpg, page2.jpg, page3.jpg, page4.jpg, page5.jpg in directory
- a 20×20 yellow box on stage instance named ‘corner’.
- a stage symbol named ‘page’ (it’s a container with nothing in it).
- four 15×15 circles on stage symbols named ‘note1,node2,node3 and node4′
- A dynamic text box called ‘angletext’.
//This frame sets up the stage, listeners and bitmapdata to use.
stop(); //do not remove stop!
var tearoff=false; var afterDrop=false; var showlines=undefined; var updateBasePage=true;
var bmpWidth; var bmpHeight; var frontpage:Sprite = new Sprite;
var matrix:Matrix=new Matrix(); var newBitmap:Bitmap; var imageLoader:Loader;
var imagePath:Array = ["page1.jpg","page2.jpg","page3.jpg","page4.jpg","page5.jpg"]; //minimum 3 images!
var bitmapData:Array=[]; var shuffle:Array=[]; var counter=0;
var imageArr:Array = new Array();
loadImage(imagePath[0]);
function loadImage(img:String):void {
imageLoader = new Loader();
imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
imageLoader.load(new URLRequest(imagePath[0]));
}
function loadComplete(e:Event):void { //loads multiple images files
imageArr.push(e.target.content);
imagePath.shift();
bitmapData[counter] = e.target.content.bitmapData; shuffle[counter]=counter; counter+=1;
bmpWidth=imageLoader.width; bmpHeight=imageLoader.height;
if (imagePath.length > 0) {loadImage(imagePath[0]);} else {setupBitmap();} //setupBitmap after last image.
}
function setupBitmap():void {
matrix.translate(page.x,page.y); //use matrix to offset the page registration points.
frontpage.graphics.beginBitmapFill(bitmapData[0],matrix,false,true); //draw frontpage.
frontpage.graphics.drawRect(page.x,page.y,bmpWidth,bmpHeight);
frontpage.graphics.endFill()
page.x=Math.round(page.x); page.y=Math.round(page.y); //integer pixels!
this.addChild(frontpage); //add frontpage to stage.
for (var i=1;i<=4;i++){ //move the four dots to front.
setChildIndex(this["node"+String(i)], this.numChildren - i);
this["node"+String(i)].alpha=0; //set dots invisible.
}
frontpage.addChild(corner); //insert the drag box at the top-left corner.
corner.x=page.x; corner.y=page.y; corner.buttonMode = true; //hand mouse pointer.
corner.addEventListener(MouseEvent.MOUSE_DOWN,OnDrag);
play(); //finished - load math functions in frame2 then stop and load frame3.
}
function foldpage(event:MouseEvent) {foldpaper()} //the main code on frame 3.
function OnDrag(event:MouseEvent):void {
if (getChildByName('newBitmap')) {removeChild(newBitmap)}; //remove the drop effect bitmap.
updateBasePage=true;
corner.startDrag();
tearoff=false;
stage.addEventListener(MouseEvent.MOUSE_MOVE,foldpage); //start the main foldpaper() code.
corner.addEventListener(MouseEvent.MOUSE_UP,DragOff);
}
function DragOff(event:MouseEvent):void {
corner.stopDrag();
corner.removeEventListener(MouseEvent.MOUSE_UP,DragOff);
stage.removeEventListener(MouseEvent.MOUSE_MOVE,foldpage); //stop the main foldpaper() code.
if (afterDrop && tearoff==true) {afterDropEffect();}
}
/*if you removing the checkboxs then remove boxChanged listeners & function, but set an afterDrop value*/
CheckBox1.addEventListener(Event.CHANGE, boxChanged)
CheckBox2.addEventListener(Event.CHANGE, boxChanged)
function boxChanged (e:Event):void {
var num;
if (CheckBox1.selected==true) {showlines = 1; num = 100;} else {showlines=undefined; num=0;}
for (var i=1;i<=4;i++){this["node"+String(i)].alpha=num}; //hide our dots.
if (CheckBox2.selected==true) {afterDrop=true;} else {afterDrop=false;} //required value for drop!
}
/*The afterDropEffect() is eye candy. Tiggered in DragOff() function above*/
var timer1:Timer=new Timer(36,36); //Timer: (delay milliseconds, repeatCount) controls number of tweens.
timer1.addEventListener(TimerEvent.TIMER,Timer1Start); //triggered by timer1.start() starts drop effects.
timer1.addEventListener(TimerEvent.TIMER_COMPLETE,Timer1Finished);
function afterDropEffect() {
var adjside = mouseX-node2.x;
var oppside = -1*(mouseY-node2.y);
var angle = Math.atan2(oppside, adjside); // in radians
angle = Math.round(angle/Math.PI*180); // convert to degrees
angletext.text = "angle: "+String(-1*(angle)); //angle of our dropped page
var tempData:BitmapData=bitmapData[shuffle[1]];
newBitmap = new Bitmap(); newBitmap.name="newBitmap"
newBitmap.bitmapData=tempData;
newBitmap.x=node2.x; newBitmap.y=node2.y; newBitmap.rotation=-1*(angle); //place at correct position.
corner.alpha=0; addChild(newBitmap);
frontpage.graphics.clear(); //remove old image.
timer1.start();
}
/*add animation flyaway effect to the dropped image */
function Timer1Start(e:TimerEvent):void {newBitmap.rotationY += 10; newBitmap.y -= 20;}
/*shuffle next 3 images to top of deck, required for multiply images*/
function Timer1Finished(e:TimerEvent):void {
timer1.reset();
angletext.text='finished';
corner.x=page.x; corner.y=page.y; corner.alpha=100; //reset the drag corner
for (var i=1;i<=shuffle.length-2;i++){ //must always have miniumum three images
shuffle.unshift(shuffle.pop()); //shuffle last items to beginning of array
}
}
Extremely Fast Line Algorithm (EFLA)

This example uses the Extremely Fast Line Algorithm By Po-Han Lin.
The chart on his website shows comparison timing against the DDA, Bresenham and Wu line algorithms. EFLA comes in several versions.
You can drag the car and target point anywhere on the stage. The car will follow the EFLA line motion path.
Also demonstrates a line motion path at various speeds.
function FastLineAlgorithm(X1,Y1,X2,Y2) { //Extremely Fast Line Algorithm By Po-Han Lin
var yLonger=false; var shortLen=Y2-Y1; var longLen=X2-X1; var incrementVal; var divDiff; var i;
if (Math.abs(shortLen)>Math.abs(longLen)) {
var swap=shortLen; shortLen=longLen; longLen=swap; yLonger=true;
}
if (longLen<0) {incrementVal=-1;} else {incrementVal=1;}
if (shortLen==0) {divDiff=longLen;} else {divDiff=longLen/shortLen;}
if (yLonger) {
for (i=0;i!=longLen;i+=incrementVal) {pts.push({x:X1+i/divDiff,y:Y1+i});}
} else {
for (i=0;i!=longLen;i+=incrementVal) {pts.push({x:X1+i,y:Y1+i/divDiff});}
}
canvas.clear();canvas.lineStyle(1,0xff0000); canvas.moveTo(pts[0].x, pts[0].y);
for (var r=1;r < pts.length-1; ++r) {canvas.lineTo(pts[r].x, pts[r].y);}
}
Download Fla CS4/AS3
Cubic Bezier motion path
Since I made a line motion path, I also decided to make a cubic Bezier motion path. Drag the control points then send the car on its way.
The only problem is the tighter the curve the smaller the distance between points are, so the car slows down. This may be good for a car as you need not take a drive in the rubarb or as Ringo said “Don’t go where the road don’t go”
CubicBezier(this,{x:p0.x,y:p0.y},{x:p1.x,y:p1.y},{x:p2.x,y:p2.y},{x:p3.x,y:p3.y});
function CubicBezier(mc,p0, p1, p2, p3) {
mc.graphics.lineStyle(2,0x0000ff); mc.graphics.moveTo(p0.x,p0.y); mc.graphics.lineTo(p1.x,p1.y);
mc.graphics.moveTo(p3.x,p3.y); mc.graphics.lineTo(p2.x,p2.y); //draw handles
mc.graphics.lineStyle(2,0xff0000); mc.graphics.moveTo(p0.x,p0.y); pts.push({x:p0.x,y:p0.y});
for (var u=0; u <= 1; u += .02) { //50 steps - draw cubic bezier arc.
var x1 = Math.pow(u,3)*(p3.x+3*(p1.x-p2.x)-p0.x)+3*Math.pow(u,2)*(p0.x-2*p1.x+p2.x)+3*u*(p1.x-p0.x)+p0.x;
var y1 = Math.pow(u,3)*(p3.y+3*(p1.y-p2.y)-p0.y)+3*Math.pow(u,2)*(p0.y-2*p1.y+p2.y)+3*u*(p1.y-p0.y)+p0.y;
mc.graphics.lineTo(x1,y1); pts.push({x:x1,y:y1});
}
mc.graphics.lineTo(p3.x,p3.y); pts.push({x:p3.x,y:p3.y});
}
Download Fla CS4/AS3
Cublic Bezier using Point.interpolate
I was looking at Wikipedia’s explanation of Bezier curves and wondered if ActionScript’s Point.interpolate would be any faster then the standard Math.pow version for making Cubic Bezier curves. The answer is NO.
Interpolate took about three times longer to build 100 curves at fifty line steps per curve.
function CubicBezierInterpolate() {
canvas.lineStyle(2,0x0000ff); canvas.moveTo(p0.x,p0.y);
for (var u=0; u <= 1; u += (1/steps)) {
var t1:Point = Point.interpolate(p1,p0,u);
var t2:Point = Point.interpolate(p2,p1,u);
var t3:Point = Point.interpolate(p3,p2,u);
var t4:Point = Point.interpolate(t2,t1,u);
var t5:Point = Point.interpolate(t3,t2,u);
var t6:Point = Point.interpolate(t5,t4,u);
canvas.lineTo(t6.x,t6.y);
}
canvas.lineTo(p3.x,p3.y);
}
(u*u*u) as apposed to Math.pow(u,3) & (u*u) for Math.pow(u,2) is about 25% faster.
var x1 = (u*u*u)*(p3.x+3*(p1.x-p2.x)-p0.x)+3*(u*u)*(p0.x-2*p1.x+p2.x)+3*u*(p1.x-p0.x)+p0.x;
var y1 = (u*u*u)*(p3.y+3*(p1.y-p2.y)-p0.y)+3*(u*u)*(p0.y-2*p1.y+p2.y)+3*u*(p1.y-p0.y)+p0.y;
ChordMaker and Vista’s Zip

I got a comment today that when trying to unzip my ChordMakerSetup.zip that Vista reported: ‘Windows cannot open folder. The compressed (zipped) Folder [filename] is invalid’
Do your self a favor and download PeaZip at http://peazip.sourceforge.net/
I have spend more time trying to fix missing Zip menu commands from Vista’s version of zip then is required by law. Vista’s zip utility is slow and basically a piece of crap and every update makes it worst.
To further learn more about this program, go to youtube.com search for: Mark Knopfler at French and Saunders
last good link was: http://www.youtube.com/watch?v=9cIdJFmFkag
Download: ChordMarkerSetup.zip
Pinball (working on Flippers)
Here’s the beginning of a really small pinball program. Currently it is only 110 lines of code. I took some parts from 4K Pinball Java code by Tom-Robert Bryntesen. The flipper code was about 50 lines of code so I’m redoing it for a smaller line count. When I have time, I’ll change the above paragraph when a new download is available.
In the mean time, the Bounce, maxSpeed and fps count are crucial. It’s not vector collision based like johanvanmol.org so, subtracting a vector on overlaps and tight corner problems where not addressed. So, I added ”Is it left or right of normal” code to stop the ball from penitrating the lines.
Thus, it only uses one-sided collision detention. However, the code can bounce off both sides of a line but fails when penitration exceeds the radius of the ball (kind of like my last girl friend).
I’m currently converting Java Ball and Line Physics code by Seoryn (YouTube) into ActionScript3. Nice stuff and very short code for a collision engine. Hopefully when I’m finished, you may never need these pinball algorithms.
What’s wrong with getBounds() in AS3?
I just started converting my old AS2 to AS3. changing all the _x, _y and _rotation text was a bit of a drag. However, everything worked out OK until I got to the getBounds() function.
I have about a dozen pinball games I’ve made. Each uses a different formula approuch (e.g. some use raw math, some use vectors, some use custom physics engines). Each have their good and bad points. All have flippers that use the getBounds() function to set the flipper pad’s collision reactions. I would nest a line clip on top of a flipper clip in order to get the sloped angle of the the flipper’s top pad. I then use getBounds() on the child (flipper.pad) and then simply add velocity to the interesected angles. I would angle this line in the edit window to the flipper’s down position.
In AS2 it worked perfectly and it only took a few lines of code to do it. On the other hand, AS3 getBounds() function seems to not work on a symbol or a child symbol that is rotated in the edit window. This was not the case in AS2.
Back to manual drawing: So here’s an example of getBounds() on a rotated shape in AS3 that works.
I used flipper1.transform.matrix for the example, but (flipper1.rotation+= steps) could be used also.
- Make a Movieclip instance of a Horizontal line, name it ‘flipper1′.
- Remark out the first 2 lines of the Shape code.
- Rotate the Movieclip Instance (also change objRotation value to the matching angle) .
- You will see that getBounds or getRect functions work correctly on a horizontal line.
- However, if you rotate the line in the edit area, aligned to 0,0 or whatever then it does not work.
- Again, this was not the case in AS2.
//You only need to play with objRotation and (rot > -45) in this example.
import fl.motion.*; var steps=-15; var KeyLEFT=false; //press the left arrow key.
var rot=999; var objRotation=15; //starting angle of shape.
//these graphic calls and addChild() not required if using a horizontal line Symbol.
var flipper1:Shape = new Shape(); flipper1.graphics.lineStyle(2,0xff0000); addChild(flipper1);
flipper1.graphics.moveTo(0,0); flipper1.graphics.lineTo(100,0); //horizontal line.
flipper1.x = stage.stageWidth/2; flipper1.y=stage.stageHeight/2; flipper1.rotation=objRotation;
function drawbounds(){ var x1,y1,x2,y2;
var r:Rectangle=flipper1.getBounds(this); //<<<< or use getRect(this)
this.graphics.lineStyle(5,0xff00ff); //deal with a slope line on flash's +- rotation values.
if(rot>=0 && rot<90 || rot>-179 && rot<-90) {x1=r.x; y1=r.y; x2=r.x+r.width; y2=r.y+r.height;}
if(rot<0 && rot>-89 || rot>=90 && rot<=180) {x1=r.x; y1=r.y+r.height; x2=r.x+r.width; y2=r.y;}
this.graphics.moveTo(x1,y1); this.graphics.lineTo(x2,y2);
//trace('x1:'+x1+' y1:'+y1+' x2:'+x2+' y2:'+y2); //here I add a function for collision response.
this.graphics.lineStyle(2,Math.round( Math.random()*0xFFFFFF ));
this.graphics.drawRect(r.x,r.y,r.width,r.height);
}
stage.addEventListener(Event.ENTER_FRAME,LeftFlipper);
stage.addEventListener(KeyboardEvent.KEY_DOWN, KeyLEFTdn);
stage.addEventListener(KeyboardEvent.KEY_UP, KeyLEFTup);
function KeyLEFTdn(e:KeyboardEvent):void {if (e.keyCode==37) {KeyLEFT=true;}}
function KeyLEFTup(e:KeyboardEvent):void {if (e.keyCode==37) {KeyLEFT=false;}}
function LeftFlipper(e:Event):void {
if(KeyLEFT==true) {
if( rot > -45) { //anything over -180 = full rotation counter-clock-wise.
var m:Matrix = flipper1.transform.matrix;
MatrixTransformer.rotateAroundInternalPoint(m,0,0,steps); //steps = m.angle
flipper1.transform.matrix = m;
rot=(int(flipper1.rotation)); drawbounds();
}
} else {
if (rot !=objRotation) { //initiate rot as 999 so we can get first values.
this.graphics.clear(); rot=objRotation; flipper1.rotation = objRotation; drawbounds();
}
}
}
