A few years ago I saved a copy of AS2 code titled “rollercoaster” posted by kirupa user icio, because it’s so cool.
I’m now getting around to converting it to AS3 and there’s a little bug I’m stuck on (bug also exists in original as2 version)
Play as3 swf here:
http://www.fastswf.com/QrbAmzE
-Draw a slope and the sprite rides the line.
-Use Arrow keys to move left/right (I added that part)
Problem:
Try to slow yourself to a near stop on a flat surface, then move again, you will coast off the line.
The ENTER_FRAME event calls tick() which calls run(); I believe the problem exists in the run function logic.
I have tried to figure it out, but failed…a lot
Here’s all the **AS3 **code
You can copy/paste this to a new document and run it. Sorry its sloppy I was in the process of converting it from as2
I have also attached the original AS2 .fla file
EDIT: found the original as2 kirupa thread from 2006!!! i feel old… I guess they were aware of the issue as well
import flash.geom.Point;
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
//CHILDREN
var ball:MovieClip= new MovieClip();
ball.graphics.lineStyle(3,0x00ff00);
ball.graphics.beginFill(0x0000FF);
ball.graphics.drawRect(-10,-10,10,10);
ball.graphics.endFill();
var track:MovieClip = new MovieClip();
var section:Shape= new Shape();
addChild(track);
//WORLD
var friction:Number = 0.97;
var gravity:Number = 0.8;
var v:Number=0;
var precision:Number = 25;//length of line segments
//VALUES
var points:Array=[];
var p:Point= new Point();
var lines:Array=[];
//USER
var drawing:Boolean = false;
var r:Boolean;
var left:Boolean;
//LISTENERS
stage.addEventListener(MouseEvent.MOUSE_DOWN, mDown);
stage.addEventListener(MouseEvent.MOUSE_UP, mUp);
stage.addEventListener(MouseEvent.MOUSE_MOVE, mMove);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keysDown);
stage.addEventListener(KeyboardEvent.KEY_UP, keysUp);
//GAME
function mDown(e:MouseEvent){
points = [];
lines = [];
drawing = true;
track.removeChildren();
track.graphics.clear();
section.x = mouseX;
section.y = mouseY;
p = new Point(mouseX, mouseY);
points.push(p);
track.graphics.lineStyle(2, 0xCCCCCC);
track.graphics.moveTo(0, mouseY);
track.graphics.lineTo(2000, mouseY);
track.graphics.moveTo(mouseX, mouseY);
}
function mUp(e:MouseEvent) {
points.push(new Point(mouseX, mouseY));
track.graphics.lineTo(mouseX,mouseY);
drawing = false;
var p1:Point, p2:Point, p3:Point, mid1:Point, mid2:Point;
p1 = linearBezierPoint([points[0], points[1]], 0.5);
//track.graphics.lineStyle(0, 0x000000);
//track.graphics.moveTo(points[0].x, points[0].y);
//track.graphics.lineTo(p1.x, p1.y);
lines.push({x: points[0].x, y: points[0].y});
if(points.length<=2){
// i added this otherwise it errored when click on stage and dont move
return;
}
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);
lines = lines.concat(bezier([mid1, p2, mid2], 20));
}
lines.push({x: p3.x, y: p3.y});
//track.graphics.lineTo(p3.x, p3.y);
for (var j:int=0; j<lines.length-1; j++) {
var a:Object = lines[j];
var b:Object = lines[j+1];
a.dx = b.x - a.x;
a.dy = b.y - a.y;
a.a = Math.atan2(a.dy, a.dx);
}
lines.pop();
track.addChild(ball);
ball.x = lines[0].x;
ball.y = lines[0].y;
ball.rotation = 180*lines[0].a/Math.PI;
v = 0;
ball.line = 0;
addEventListener(Event.ENTER_FRAME, tick);
}
function tick(e:Event){
if(drawing){
return;
}
//USER MOVEMENT
if(left&& v>-10){
v-=.4;
//friction=.999;
}else if(r&&v<10){
v+=.4;
//friction=.999;
}else{
//friction=.9999;
}
var l:Object = lines[ball.line];
if(!l){return;}
v += Math.sin(l.a)*gravity;
v *= friction;
run(v);
ball.rotation = 180/Math.PI*lines[ball.line].a;
/* for(var id:String in l) {
var value:Object = l[id];
trace(id + " = " + value);
}
removeEventListener(Event.ENTER_FRAME, tick);*/
}
function run(distance) {
var l = lines[ball.line];
//trace(ball.line);
if (v == 0) {
return;
}
var ex:Number = l.x, ey:Number = l.y;
if (v >= 0) {
ex += l.dx;
ey += l.dy;
}
var dx:Number = ex - ball.x;
var dy:Number = ey - ball.y;
var d:Number = Math.sqrt(dx*dx + dy*dy);
if (d < Math.abs(distance)) {
ball.x = ex;
ball.y = ey;
ball.line += v > 0 ? 1 : -1;
if (ball.line == -1 || ball.line == lines.length) {
ball.line -= v > 0 ? 1 : -1;
v *= -0.3;
} else {
run((Math.abs(distance) - d)*Math.abs(distance)/distance);
}
} else {
ball.x += distance*Math.cos(l.a);
ball.y += distance*Math.sin(l.a);
}
}
function mMove(e:Event) {
if (!drawing) return;
var dx:Number = mouseX - p.x;
var dy:Number = mouseY - p.y;
var d:Number = Math.sqrt(dx*dx+dy*dy);
if (d >= precision) {
var a:Number = Math.atan2(dy, dx);
p = new Point(p.x+precision*Math.cos(a), p.y+precision*Math.sin(a));
points.push(p);
section.x = p.x;
section.y = p.y;
//unknownDrawFunction()
track.graphics.lineTo(p.x, p.y);
mMove(null);
//trace("why is it calling itself");
}
}
function linearBezierPoint(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
);
}
function quadraticBezierPoint(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
);
}
function bezier(p:Array, segments:Number):Array {
if (segments < 1){
return null;
}
var func:Function;
if (p.length < 2) {
return null;
} 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 null;
}
var pr:Array = [];
var dt:Number = 1/segments;
var s:Point = func(p, 0);
track.graphics.moveTo(s.x, s.y);
for (var i:Number=1; i<=segments; i++) {
s = func(p, i*dt);
pr.push({x: s.x, y: s.y});
track.graphics.lineTo(s.x, s.y);
}
return pr;
}
//UNKNOWN
function unknownDrawFunction(){
//I dont know what this function was for, im not calling it
if(!drawing){
return;
}
section.graphics.clear();
section.graphics.lineStyle(1, 0x666666);
section.graphics.lineTo(mouseX, mouseY);
// updateAfterEvent();
}
//USER
function keysDown(e:KeyboardEvent){
if(e.keyCode==37){
left=true;
r=false;
}else if(e.keyCode==39){
r=true;
left=false;
}
}
function keysUp(e:KeyboardEvent){
if(e.keyCode==37){
left=false;
}else if(e.keyCode==39){
r=false;
}
}