# Icio’s rollercoaster code (like line rider)

**URL:** https://forum.kirupa.com/t/icio-s-rollercoaster-code-like-line-rider/332154
**Category:** flash
**Created:** [February 17, 2014, 3:10pm UTC](https://forum.kirupa.com/t/icio-s-rollercoaster-code-like-line-rider/332154 "2014-02-17T15:10:24Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![tbo](https://avatars.discourse-cdn.com/v4/letter/t/7feea3/32.png) [@tbo](https://forum.kirupa.com/u/tbo)
#### Post date: [February 17, 2014, 3:10pm UTC](https://forum.kirupa.com/t/icio-s-rollercoaster-code-like-line-rider/332154/1 "2014-02-17T15:10:24Z")

</div>

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](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

> **[Rollercoaster](https://www.kirupa.com/forum/showthread.php?245203-Rollercoaster&highlight=rollercoaster)**
>
> Got a web design/development question or just want to hang out with the most awesome people on the planet? Drop on in!

```php

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;
    
    }
}

```

---

<div class="post-metadata">

### Author: ![Userpass12453](https://avatars.discourse-cdn.com/v4/letter/u/77aa72/32.png) [@Userpass12453](https://forum.kirupa.com/u/Userpass12453)
#### Post date: [October 10, 2014, 10:50pm UTC](https://forum.kirupa.com/t/icio-s-rollercoaster-code-like-line-rider/332154/2 "2014-10-10T22:50:37Z")

</div>

Did you ever get this resolved in your project?

This is what I had put together after learning how to make a game out of that code, wasn’t amazing in my eyes but came out decent.

[http://3dmitchell.com/miner/](http://3dmitchell.com/miner/)

[QUOTE=tbo;2660674]Yeah looks like you did fix that, nice!  
I spent quite a while with it last night, I got to the understanding that

```auto
ball.line += v > 0 ? 1 : -1; 

```

increases the pointer of which lines object (coordinates and more)to target next,  
lines[ball.line] // (coordinates and more)

but because of the failed logic it gets stuck where

```auto
if (d < Math.abs(distance)) {

```

is always false, thus never updating the next pointer

```auto
…or something

```

[/QUOTE]

---

<div class="post-metadata">

### Author: ![tbo](https://avatars.discourse-cdn.com/v4/letter/t/7feea3/32.png) [@tbo](https://forum.kirupa.com/u/tbo)
#### Post date: [October 16, 2014, 11:22pm UTC](https://forum.kirupa.com/t/icio-s-rollercoaster-code-like-line-rider/332154/3 "2014-10-16T23:22:44Z")

</div>

I did not get it fixed, I dont even remember what I was doing with it but I still would like to fix it some day. I assume you have the same problem?

I can’t see your swf at the moment

---

<div class="post-metadata">

### Author: ![Userpass12453](https://avatars.discourse-cdn.com/v4/letter/u/77aa72/32.png) [@Userpass12453](https://forum.kirupa.com/u/Userpass12453)
#### Post date: [October 18, 2014, 6:43pm UTC](https://forum.kirupa.com/t/icio-s-rollercoaster-code-like-line-rider/332154/4 "2014-10-18T18:43:08Z")

</div>

[QUOTE=tbo;2662988]I did not get it fixed, I dont even remember what I was doing with it but I still would like to fix it some day. I assume you have the same problem?

I can’t see your swf at the moment[/QUOTE]

Well, once you can see the game with a modern browser I’d say that’s a start.

I am using IE10, Firefox, and Chrome with no issue viewing.

---

<div class="post-metadata">

### Author: ![tbo](https://avatars.discourse-cdn.com/v4/letter/t/7feea3/32.png) [@tbo](https://forum.kirupa.com/u/tbo)
#### Post date: [October 25, 2014, 10:57am UTC](https://forum.kirupa.com/t/icio-s-rollercoaster-code-like-line-rider/332154/5 "2014-10-25T10:57:25Z")

</div>

i meant to say I was on a phone at the time with no flash.

anyway I like it, its a nice game for sure, I do recommend some 1920’s chimney sweep looking guys piled in the cart that plummet to their death upon crashing.:be: but then again that’s always my solution

So did you end up dealing with the original issue of the cart veering off track at low velocity? I did not seem to have the problem with your game, perhaps you just added enough friction that it stops before you get to that point?

---

<div class="post-metadata">

### Author: ![Userpass12453](https://avatars.discourse-cdn.com/v4/letter/u/77aa72/32.png) [@Userpass12453](https://forum.kirupa.com/u/Userpass12453)
#### Post date: [October 25, 2014, 8:57pm UTC](https://forum.kirupa.com/t/icio-s-rollercoaster-code-like-line-rider/332154/6 "2014-10-25T20:57:30Z")

</div>

No problem, thanks! 🙂

Yes, I did end up dealing with the cart veering off at low velocity and I didn’t proceed with making a second level until I had that figured out. I believe I did some sort of check on the ball speed and adjusted accordingly, I would have to open up my source to check for ya but if ya need it I can definitely open it up. The boost pads were something extra I added in and they can only be used a few times each because initially you could draw a ultra long line and use the boost pad to go in circles. An ultra long line could end up crashing flash on a slow system as the computation required to draw 1k-10k track pieces (the actual curve the ball takes as well as the visual line to the user) was quite intense. I did end up adding in a maximum track length check for drawing and boost limiter with colors that changed to let you know the level of boost left.

---

<div class="post-metadata">

### Author: ![tbo](https://avatars.discourse-cdn.com/v4/letter/t/7feea3/32.png) [@tbo](https://forum.kirupa.com/u/tbo)
#### Post date: [October 25, 2014, 9:29pm UTC](https://forum.kirupa.com/t/icio-s-rollercoaster-code-like-line-rider/332154/7 "2014-10-25T21:29:52Z")

</div>

im not doing anything right now, so no need to open your code up but thanks. if u do come by it some time post it here though. I might make something somedayI think I recall experimenting with making the track segments longer as a way to pull a little more performance out of it also
