Sonic Running Physics

100 views
Skip to first unread message

cel...@gmail.com

unread,
Apr 15, 2014, 2:37:50 PM4/15/14
to mel...@googlegroups.com
Hi Everyone !

I am newbie on melonJs and i am trying implement the Sonic Hedgehog Running Physics on MelonJs Tutorial game, i have a little dificulty to "translate" some concepts to Melon JS engine, like how to use this.accel.x, this.vel.x and this.maxVel.x in this case? (or other entity properties)

dec = 0.5
max = 6

{
 if the player is pressing left
   {
   if X speed > 0
     {
     X speed -= dec
     }
   else
   if X speed > -max
     {
     X speed = X speed - acc
     }
     else X speed = -max
   }
 else
 if the player is pressing right
   {
   if X speed < 0
     {
     X speed += dec
     }
   else
   if X speed < max
     {
     X speed = X speed + acc
     }
     else X speed = max
   }
 }


Thanks,
Celso

Jay Oster

unread,
Apr 16, 2014, 1:55:33 AM4/16/14
to mel...@googlegroups.com, cel...@gmail.com
Hi.

this.accel.x is "acc"
this.friction.x is "frc"
this.maxVel.x is "max"
this.vel.x is "X speed"

There is no corresponding vector in melonJS for "dec", but you can easily add one if you like...

this.dec = new me.Vector2d(0.5, 0);

After computing the velocity vector (this.vel) using the algorithm described on the site, call this.updateMovement(); to apply the velocity to the object's position. Friction and velocity clamping will be applied automatically by this method.

cel...@gmail.com

unread,
Apr 17, 2014, 12:58:03 PM4/17/14
to mel...@googlegroups.com, cel...@gmail.com
 
Hi Jay,
Thanks for the answer

Take a look at my first version:
 
 http://celsowm.altervista.org/sonic-js/index.html

I did the "dec" manually with "0.5".

My next challenge is the the gradative deceleration after the first steps like genesis games (Sonic walks some steps after you release the button)

Thanks !

Jay Oster

unread,
Apr 17, 2014, 5:36:32 PM4/17/14
to mel...@googlegroups.com, cel...@gmail.com
Hi,

Decelerate is handled by the friction vector. You are explicitly setting the velocity to zero when no keys are pressed, and additionally doing some "strange" things which are not very melonJS-like, and also not very Sonic-like. Here's how I changed it:

In "init", I setup the physics constants:

// Sonic physics
this.setVelocity(0.046875 * 4, 15);
this.setMaxVelocity(6 * 2, 15);
this.setFriction(0.046875 * 2, 0);
this.dec = new me.Vector2d(0.5, 0);

Then in the "update" method, I totally rewrote the input handling code to only set the velocity vector (ignoring the algorithm described in the physics article, because melonJS already does ALL of that for you when you call this.updateMovement). What you are left with is a very, very simple input handler:

if (me.input.isKeyPressed('left'))
{
    // flip the sprite on horizontal axis
    this.flipX(true);

    // Set velocity
    this.vel.x -= (
        (this.vel.x <= 0) ? this.accel.x : this.dec.x
    ) * me.timer.tick;
}
else if (me.input.isKeyPressed('right'))
{
    // unflip the sprite
    this.flipX(false);

    // Set velocity
    this.vel.x += (
        (this.vel.x >= 0) ? this.accel.x : this.dec.x
    ) * me.timer.tick;
}


//jump
if (me.input.isKeyPressed('jump'))
{
    // ... jump stuff here
}

this.updateMovement();

And there you go! It acts a lot more like Sonic, now. It's not a perfect clone, for sure. But it's close. And with some tweaks, you can still get it closer.

You will notice I've done a few things different with the constants. Most importantly, the Genesis Sonic games run at 30fps, so I've doubled the constants for 60fps in melonJS. Second, I've doubled the acceleration constant *AGAIN* to counteract the friction (which is applied regardless of whether you are holding directions). But overall it is very similar.

The last bit of info to divulge is that setting the velocity in the input handlers will select either the acceleration constant or the deceleration constant, depending on the direction your Sonic is already moving. It does not handle the quirk regarding max deceleration when Sonic is moving too slow. And as mentioned, it may not be worth adding that.

Give it a try, and let us know what you think!

cel...@gmail.com

unread,
Apr 18, 2014, 12:51:26 PM4/18/14
to mel...@googlegroups.com, cel...@gmail.com
Hi Jay,

Take a look at the new version:
http://celsowm.altervista.org/sonic-js/index.html

Thanks Very Much !!!

Now i am trying to understand how to change the animation sprite when sonic reach the "max speed"
(and the "jump" and "stop" too)

Jay Oster

unread,
Apr 18, 2014, 2:27:32 PM4/18/14
to mel...@googlegroups.com, cel...@gmail.com
That does look and feel much better, now! ^_^

Managing animations can be hard! Which I'm sure you will discover. But you can select between the "walk" and "top_speed" animations after calling this.updateMovement();

this.updateMovement();

if (!this.jumping) {
    if (Math.abs(this.vel.x) >= (this.maxVel.x / 2)) {
        if (!this.isCurrentAnimation("walk")) {
            this.setCurrentAnimation("top_speed");
        }
    }
    else if (!this.isCurrentAnimation("top_speed")) {
        this.setCurrentAnimation("walk");
    }
}

This will select the correct animation depending on how fast Sonic is moving. You can tweak the second condition to change how fast sonic must be moving before the animation switches. I chose half of his max velocity as the trigger. Also I wrapped the entire thing in a condition so the switch cannot happen after Sonic has jumped. This way you can easily uncomment the "jump" animation code and it should all just work correctly; the jump animation won't get interrupted until Sonic has landed.

The next thing you should be aware of is setting the "stop" animation properly. The same logic can be used: if velocity is 0 and current animation is not "stop", set animation to "stop".

Then you can start dealing with the idle animations, edge balancing animations, spin dash animations, etc.
Reply all
Reply to author
Forward
0 new messages