Some people (actually, just one person) asked us on how we modelled the movement physics of CrossCode, e.g. how does the keyboard input influence the movement speed of the player.
Thus, in this post we’ll write about CrossCode’s movement physics.
First of all: These physics are not modelled after reality but rather on how well it played out.
Each movable entity in CrossCode has the following value to describe it’s physical state (written in JavaScript syntax):
{ // the current position of the entity in 3 dimensional space: pos: { x: 0, y: 0, z: 0), // the current velocity in 3 dimensional space: velocity: {x: 0, y: 0, z: 0), // the current direction of acceleration: accelDir: {x: 0, y: 0, z: 0), // the maximum velocity the entity can achieve through acceleration: maxVel: 300, // The speed of acceleration accelSpeed: 1.0, // the friction that determines how fast the entity will brake on ground: friction: 1.0, // airfriciton, same as friction, only valid when entity is above the ground airFriction: 0.2 }
About the coordinates: CrossCode has 3 dimensional coordinates, whereas the x and y coordinate are the ground coordinates and z the height coordinate (positive z means above ground).
The movement physics described here only modify the ground coordinates of the entity. We won’t cover the height coordinate modification in this post. (Just write us, if you want to know about these as well).
The genereal idea about the physics is (still similar to impact.js), that entities only modify their velocity directly or indirectly via accelDir, maxVel and friction. The resulting velocity is used to update the entities position, considering collision with the surrounding.
Here is how the accelDir, maxVel and friction determine the velocity:
First of all, all computations depend either on normal friction or airFriction, if the entity is above ground:
var friction = [entity above ground] ? this.airFriction : this.friction;
We compute the final acceleration vector using accelDir, accelSpeed, maxVel and friction like so:
var accelDir = Vec2.mulF(this.accelDir, this.maxVel * 10 * friction * this.accelSpeed * ig.system.tick, true);
Note, we are using custom functions for vector operations like Vec2.mulF(). I posted those functions here. Also, ig.sytem.tick is the time interval of the current frame (as known from impact.js) and 10 some magic number to balance the friction input value.
So, what we got is an entity with a current velocity and acceleration:
Next we compute the friction vector that is used to reduce the current acceleration:
var frictionVel = Vec2.mulF(this.vel, friction * 12 * ig.system.tick, true);
Note: 12 is another some magic number to balance the impact of the friction input value.
We get the following vector:
Now comes an interesting step. We will trim down any friction that is in the direction of the current acceleration. That way, the friction won’t slow down acceleration too much and still reduce orthogonal velocity fast enough to move the entity in the direction of the acceleration. Note: we skip this step, if the current velocity is faster than maxVel or in the opposite direction of accelDir. In that case we do want to reduce the speed of velocity, so no friction is trimmed.
var velLength = Vec2.length(this.vel); if(velLength <= this.maxVel){ var dot = Vec2.dot(this.accelDir, frictionVel); if(dot >= 0){ Vec2.sub(frictionVel, Vec2.mulF(this.accelDir, dot, true)); } }
Now, we will apply the acceleration.
this.vel.x += accelDir.x ; this.vel.y += accelDir.y ;
The length of the resulting velocity is reduced to be the maximum of minVel or the previous length (in case the previous velocity was faster than maxVel – remember that maxVel is only the maximal velocity we achieve with acceleration, so it should not apply if the velocity has been already faster than maxVel before applying acceleration).
Vec2.limit(this.vel, 0, Math.max(velLength, this.maxVel));
Finally, we reduce the velocity by the previously computed friction:
this.vel.x -= frictionVel.x; this.vel.y -= frictionVel.y;
And that’s the whole thing.
This algorithm might seem weird and not very intuitive. That’s because we just adapted the code until the resulting movement felt right.
Feel free to try the same thing for your game. It might just work for you as well!
12 Comments
Really interesting! Thanks for sharing this. I’d love to read about the height coordinate modification :)
Hi there!
Your comment hasn’t been missed. :D
There is not such much to write about height coordinate modifications, but I’ll try to write something about it soon.
It’s look like complicated thing. But it seems interesting for people who study programming. My friends who are IT experts may also open this site. Thank you for providing this information.
I intereseted with programming. I also gamers, sometimes I imagined I can build a game, about water galon delivery. oh that’s just my imagine. from your post it looks complicated. I have learned about Visual basic or C++ languange in university.
I wonder how collision detection is handled.
I’ve studied computational physics and made some model visualization using some formulas. I wonder can be at that moment again. So inspiring, thanks!
Very interesting, but unfortunately I do not like complex, is very suitable for a programmer, maybe .. hehe
great way to learn and modified / modding crosscode! should try this in the game
Thank you for this article. Very helpful indeed especially for the beginners like me. Thank you. Keep it up.
Such an efficient article! Please keep update your blog thanks.
I wonder how collision detection is handled.
very unique game, which is very training motor skills