The forums have permanently moved to forum.kirupa.com. This forum will be kept around in read-only mode for archival purposes. To learn how to continue using your existing account on the new forums, check out this thread.


Results 1 to 15 of 15

Thread: Icio’s rollercoaster code (like line rider)

  1. #1
    974
    posts
    Registered User

    Icio’s rollercoaster code (like line rider)

    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
    http://www.kirupa.com/forum/showthre...=rollercoaster

    PHP Code:
    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_DOWNmDown);
    stage.addEventListener(MouseEvent.MOUSE_UPmUp);
    stage.addEventListener(MouseEvent.MOUSE_MOVEmMove);
    stage.addEventListener(KeyboardEvent.KEY_DOWNkeysDown);
    stage.addEventListener(KeyboardEvent.KEY_UPkeysUp);


    //GAME

    function mDown(e:MouseEvent){
        
        
    points = [];
        
    lines = [];
        
        
    drawing true;
        
        
    track.removeChildren();    
        
    track.graphics.clear();

        
    section.mouseX;
        
    section.mouseY;
        
        
        
    = new Point(mouseXmouseY);
        
    points.push(p);
        
        
    track.graphics.lineStyle(20xCCCCCC);
        
    track.graphics.moveTo(0mouseY);
        
    track.graphics.lineTo(2000mouseY);
        
    track.graphics.moveTo(mouseXmouseY);
    }


    function 
    mUp(e:MouseEvent) {
        
    points.push(new Point(mouseXmouseY));
        
    track.graphics.lineTo(mouseX,mouseY);
        
        
    drawing false;

        var 
    p1:Pointp2:Pointp3:Pointmid1:Pointmid2: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({xpoints[0].xypoints[0].y});

        if(
    points.length<=2){
            
    //    i added this otherwise it errored when click on stage and dont move
            
    return;
        }
        
        for (var 
    i:Number=0i<points.length-2i++) {
            
            
    p1 points[i];
            
    p2 points[i+1];
            
    p3 points[i+2];
            
    mid1 linearBezierPoint([p1p2], 0.5);
            
    mid2 linearBezierPoint([p2p3], 0.5);        
            
    lines lines.concat(bezier([mid1p2mid2], 20));
        }
        

        
    lines.push({xp3.xyp3.y});
        
        
        
    //track.graphics.lineTo(p3.x, p3.y);
        
        
        
    for (var j:int=0j<lines.length-1j++) {

            var 
    a:Object lines[j];
            var 
    b:Object lines[j+1];
            
    a.dx b.a.x;
            
    a.dy b.a.y;
            
    a.Math.atan2(a.dya.dx);
        }
        
        
    lines.pop();
        
    track.addChild(ball);
        
        
    ball.lines[0].x;
        
    ball.lines[0].y;
        
    ball.rotation 180*lines[0].a/Math.PI;
        
    0;
        
    ball.line 0;
        
        
    addEventListener(Event.ENTER_FRAMEtick);

    }

    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;}
            
    += Math.sin(l.a)*gravity;
            
    *= 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 
    lines[ball.line];
        
    //trace(ball.line);
        
    if (== 0) {
            return;
        }

        var 
    ex:Number l.xey:Number l.y;
        if (
    >= 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 (
    Math.abs(distance)) {
                
            
    ball.ex;
            
    ball.ey;
            
    ball.line += : -1;
            if (
    ball.line == -|| ball.line == lines.length) {
                
    ball.line -= : -1;
                
    *= -0.3;
            } else {
                
    run((Math.abs(distance) - d)*Math.abs(distance)/distance);
                
            }
        } else {
            
    ball.+= distance*Math.cos(l.a);
            
    ball.+= 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 (
    >= precision) {
            var 
    a:Number Math.atan2(dydx);
            
    = new Point(p.x+precision*Math.cos(a), p.y+precision*Math.sin(a));
            
    points.push(p);
            
            
    section.p.x;
            
    section.p.y;
            
    //unknownDrawFunction()
            
    track.graphics.lineTo(p.xp.y);
            
            
    mMove(null);
            
    //trace("why is it calling itself");
        
    }
    }



    function 
    linearBezierPoint(p:Array, t:Number):Point {
        if (
    || || 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 (
    || || p.length != 3){
            return 
    null;
        }
       
        var 
    ax:Numberbx:Number;
        
    bx 2*(p[1].x-p[0].x);
        
    ax p[2].p[0].bx;
       
        var 
    ay:Numberby:Number;
        
    by 2*(p[1].p[0].y);
        
    ay p[2].p[0].by;
       
        var 
    t2:Number t*t;
       
        return new 
    Point(
            
    ax*t2 bx*p[0].x,
            
    ay*t2 by*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(p0);
        
    track.graphics.moveTo(s.xs.y);
       
        for (var 
    i:Number=1i<=segmentsi++) {
            
    func(pi*dt);
            
    pr.push({xs.xys.y});
            
    track.graphics.lineTo(s.xs.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(10x666666);
            
    section.graphics.lineTo(mouseXmouseY);
        
    //    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;
        
        }

    Attached Files Attached Files
    Last edited by tbo; February 17th, 2014 at 11:19 AM.

  2. #2
    I changed the last significant line of run (roughly line 194) to include a clamping conditional expression and things seemed to be fine after that:

    if(Math.abs(l.a) > 0.05) ball.y += distance*Math.sin(l.a);

    My rationale for trying that was that errors tend to accumulate quickly when dealing with small numbers, and things sliding on a nearly flat line shouldn't be going up.
    “Who were you, Krilnon, and how did you know so much about AS4?”
    The historian sighed as she gazed up at the sky and saw… not stars. A story.

  3. #3
    974
    posts
    Registered User
    I dont seem to be able to get it working, can you post the whole function

  4. #4
    PHP Code:
    function run(distance) {
        
        var 
    lines[ball.line];
        
    //trace(ball.line);
        
    if (== 0) {
            return;
        }

        var 
    ex:Number l.xey:Number l.y;
        if (
    >= 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 (
    Math.abs(distance)) {
                
            
    ball.ex;
            
    ball.ey;
            
    ball.line += : -1;
            if (
    ball.line == -|| ball.line == lines.length) {
                
    ball.line -= : -1;
                
    *= -0.3;
            } else {
                
    run((Math.abs(distance) - d)*Math.abs(distance)/distance);
                
            }
        } else {
            
    ball.+= distance*Math.cos(l.a);
            if(
    Math.abs(l.a) > 0.05ball.+= distance*Math.sin(l.a);
        }

    http://reclipse.net/kirupa/line-magnet.swf

    It's still susceptible to flying off if you stop it on a steeper slope, but I didn't spend that much time trying to understand the code, just the problem you described. And the constant (0.05) was just a guess.
    “Who were you, Krilnon, and how did you know so much about AS4?”
    The historian sighed as she gazed up at the sky and saw… not stars. A story.

  5. #5
    974
    posts
    Registered User
    Thanks, but it seems to act the same, at least in the swf you posted. Even without moving left or right it will fly off (sometimes) right before it comes to a rest at the bottom of the arch

  6. #6
    Oh well, I tried.
    “Who were you, Krilnon, and how did you know so much about AS4?”
    The historian sighed as she gazed up at the sky and saw… not stars. A story.

  7. #7
    974
    posts
    Registered User
    Thanks i really appreciate it, im going to try to play around with the logic you said later on. I don't really need this for anything specific I just got stuck on it playing around and now im kind of obsessed with figuring it out

  8. #8
    I think the obsession is key. I saw this when I woke up this morning, looked at it a bit, but then decided I didn't really want to mess around with the kinda-sorta physics code. But then I looked at it again and thought I could fix it. But I don't really want to try to understand all of the code.

    FWIW, I think I did fix the part where it would start hovering upwards if you stopped it on a flat surface and kind of jiggled it around a bit.
    “Who were you, Krilnon, and how did you know so much about AS4?”
    The historian sighed as she gazed up at the sky and saw… not stars. A story.

  9. #9
    974
    posts
    Registered User
    Yeah looks like you did fix that, nice!
    I spent quite a while with it last night, I got to the understanding that

    Code:
    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
    Code:
    if (d < Math.abs(distance)) {
    is always false, thus never updating the next pointer

    Code:
    …or something

  10. #10
    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/

    Quote Originally Posted by tbo View Post
    Yeah looks like you did fix that, nice!
    I spent quite a while with it last night, I got to the understanding that

    Code:
    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
    Code:
    if (d < Math.abs(distance)) {
    is always false, thus never updating the next pointer

    Code:
    …or something

  11. #11
    974
    posts
    Registered User
    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

  12. #12
    Quote Originally Posted by tbo View Post
    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
    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.

  13. #13
    974
    posts
    Registered User
    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. 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?

  14. #14
    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.

  15. #15
    974
    posts
    Registered User
    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

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  

Home About kirupa.com Meet the Moderators Advertise

 Link to Us

 Credits

Copyright 1999 - 2012