Here's my entry...
Basically, there are a few coefficients that you can tweak at the top to change how it acts and probably get a bit closer to "real" than what I did, but the physics are pretty exact.
I did take a whole lot of things out of what real ice skating physics would be because we only have a certain level of control (i.e., we can't change what angles the skates are pointing at or exactly how much power we want per stroke), but I made a few estimations as to how to replicate what a normal person would do.
And the code:
PHP Code:
//#CLIENTSIDE
function onCreated() {
disabledefmovement();
this.velocity = {0,0,0}; // inital velocity vector
this.power = 1; // power per stroke (should be less than 1 or you might get weird results)
this.friction = .95; // friction coefficient
this.collision = -.5; // collision coefficient
this.scale = .5; // velocity -> tiles
this.foot = 1; // current foot
onTimeout();
}
function onTimeout() {
if (keydown(0) || keydown(1) || keydown(2) || keydown(3)) { // if a key is pressed
if (this.cooldown <= 0) { // if the cooldown is finished
// alternate current foot
this.foot = -this.foot;
// set the ani, would make more sense if I had one for each foot, but just sticking with defaults
setani("walk", null);
// set the direction
player.dir = getdir((keydown(3)-keydown(1)), (keydown(2)-keydown(0)));
// normalized movement vector based on key input
temp.movement = vectornormalize({(keydown(3)-keydown(1)), (keydown(2)-keydown(0)), 0});
// rotate movement vector slightly based on which foot the stroke is coming from and how fast the player is traveling
temp.movement = getvectorfromangles(getanglesfromvector(temp.movement)[0]+this.foot*vectorlen(this.velocity)^2.5/8, 0);
// scale movement vector
temp.movement = vectorscale(temp.movement, this.power);
// add the movement vector to the player velocity vector
this.velocity = vectoradd(this.velocity, temp.movement);
// add a cooldown variable until next stroke based on how fast the player is traveling
this.cooldown = int(vectorlen(this.velocity)*2);
} else {
setani("idle", null);
}
} else {
setani("idle", null);
}
this.cooldown--; // decrease cooldown
if (vectorlen(this.velocity) < .1) { // just so it doesn't do a bunch of calculations for more or less no reason
this.velocity = {0,0,0};
} else {
this.velocity = vectorscale(this.velocity, this.friction); // apply the friction coefficient
// collision detection
temp.t = 7;
for (temp.i = 1; temp.i <= temp.t; temp.i++) { // partition the checking into temp.t parts
// if the next point is not on a wall
if (!onwall2(player.x+((this.velocity[0]*this.scale)/temp.t), player.y+((this.velocity[1]*this.scale)/temp.t), 2, 3)) {
// move onto the next point
player.x += (this.velocity[0]*this.scale)/temp.t;
player.y += (this.velocity[1]*this.scale)/temp.t;
} else {
// scale the vector with the collision coefficient
this.velocity = vectorscale(this.velocity, this.collision);
}
}
}
setTimer(0.05);
}
The coefficients I set should more or less replicate a player with ice skates on.
For a player with ice skates off I would probably use the following constants:
PHP Code:
this.power = .1; // power per stroke (should be less than 1 or you might get weird results)
this.friction = .99; // friction coefficient
this.collision = -.1; // collision coefficient