Jump to content
  • Advertisement

Project: The Berg

Slopey McSlopeface (part 1)

Greedy Goblin


Hmmm, I love sausage rolls. 

Oh sorry, just having a tasty sausage roll for my lunch while thinking about the problem of... slopes.

So I have this nice terrain an' all, that I can now walk around on.  But those hills aren't exactly challenging my player character.  I breeze up those as easily as I descend a vertical drop.  Why is that?  Because I'm just making the player follow the terrain like it's on rails, that's why!  No fancy pants physics engines here guv.

I need to make the player ascend steep inclines more slowly than flat terrain and also come to a halt against any vertical, or near-vertical inclines.  I also need to make the player fall or tumble if they attempt to go down any incline too steep... but that's for another blog.

I first messed around with attempting to stop the player if they tried to walk up anything with a gradient over a certain threshold... that didn't work out too well.  Lots of jittery movement ensued.  Then I realised my approach was all wrong!  When I climb a steep hill, I don't just come to a dead stop in reality, I just move more slowly as I ascend.  So this just became a case of factoring in the terrain gradient to my player speed... simples!

// Test slope in direction of travel
let direction = new THREE.Vector3().copy( this.collisionBody.resolveMoves().normalize() );
let p1 = new THREE.Vector3().copy( this.position );
let intersection1 = _this.terrain.heightAt( p1.x, p1.z );

let p2 = new THREE.Vector3().addVectors( this.position, direction );
let intersection2 = _this.terrain.heightAt( p2.x, p2.z );

let grad = intersection2.h - intersection1.h;
_this.playerController.currentSpeed = Math.clamp( -_this.playerController.DEFAULT_SPEEDS.WALKING * grad + _this.playerController.DEFAULT_SPEEDS.WALKING, 0, 2 );

Works a treat.... except (sigh) when I'm up against a near vertical incline.  I can still climb those, just a bit more slowly (sigh).  In fact, no, this doesn't look right at all.  The graident should be so large when approaching a near vertical incline that it should reduce my speed to 0.  But for some reason I get this....

Much head scratching ensued!

Then I realised it must be something to do with the order of processing.  The way I handle movement is through a "CollisionBody" object which is attached to the player.  I call a "move" function on the CollisionBody which basically stores it in an array until the "PhysicsManager" decides to resolve it (reminder: there is no fancy physics going on at all yet... I just decided to call it a PhysicsManager).  The thing is, my PlayerController was calling "move" before I had changed my speed to zero, so the movement vectors were already baked in (I know, I know, this is getting complicated already!) and changing the speed did nothing.  Each alternate frame I was then resetting my speed back to normal walking speed....

You know, it's only when I write all that down I see just how crazy dumb it was!  😂

So I decided on an alternative approach.  Instead of setting an absolute velocity vector when calling CollisionBody.move I now pass a direction vector and speed as a new Velocity object... however... the speed doesn't have to be a number... it can be a function!  Thereby I can delay the resolution of the velocity until absolutely necessary (i.e. when the PhysicsManager needs to apply the moves).  It may sound complicated but I quite like it.  I can then make any other adjustments to the speed (not velocity) during the frame update and it will take effect when the PhysicsManager resolves everything!


  1. PlayerController handles movement -> player.collisionBody.move( new Velocity( direction, () => player.speed )
  2. Player object "update" tests for slopes and adjusts speed accordingly
  3. PhysicsManager "update" resolves all player.collisionBody movements, in turn resolving all Velocity values using the new updated speed rather than the speed as it was in step 1

So how does this work out now?

Better... if you watch very closely you might notice I've added in a subtle acceleration too which gives a smoother feel to the player movement (later I'll add in head bobbing).  However, I'm still not entirely happy with it.  When you stop the player doesn't decelerate, but comes to an abrupt stop... which is fine but feels a little unnatural.  Near vertical inclines are also handled better, although I still find with the "right" movements I can still climb them so I definitely need to work on this more.

Acceleration is done by adding in a targetSpeed property on the Player, so the actual speed will accelerate towards that speed until it is reached.  It does decelerate too as the incline increases, but when you lift your key from the keyboard the direction vector is reset to {0, 0, 0} so the speed has no effect.  :(

I'll have a think a bit more about this later.  Ideas and suggestions are welcome!



Recommended Comments

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Advertisement
  • Advertisement
  • Blog Entries

  • Similar Content

    • By Ewe Tek Min
      Shiba's Adventure
      If you are a dog lovers, you must not miss this epic RPG roguelike game that you've never seen. In this turn-based roguelike RPG game, you have to pick your cute favorite dog and dive into the perilous dungeons. Simply move by swiping on your screen when you are exploring the dungeon.
      • You have to avoid all the bad people whom trying to catch you to be their pet because of your cuteness! When you go into deeper dungeon, more bad people will try to catch you, just stay away from them!
      • Besides avoiding those bad people, you also need to keep your stomach full in order to survive through the deep dungeon. Don't forget to ingest some foods while you are crawling the dungeon, otherwise you will be starved to death.
      • Plan your move carefully as every move will cause you energy and you will be perish once your run out your energy.
      • More than 15 kind of adorable and cute dogs to unlock and play! Many more are coming soon!
      • Turn-based gameplay
      • Simply swipe to move your dog 
      • Randomly generated levels provide a different game experience every time!
      • Compete with your friends and see who can survive the dungeon longest!
      Leave your review or feedback to us if you can't find your favorite dogs in the game and we will create for you!
      Download now from App Store: Coming soon
      Download now from Google Play: Coming soon
    • By simco50
      I have regular matrix-based skinning on the GPU working for quite a while now and I stumbled upon an implementation of Dual Quaternion skinning.
      I've had a go at implementing this in a shader and after spending a lot of time on making small changes to the formulas to make it work, I sort of got it working but there seems to be an issue when blending bones.
      I found this pretty old topic on GameDev.net (
      ) which, I think, describes my problem pretty well but I haven't been able to find the problem.
      Like in that post, if the blendweight of a vertex is 1, there is no problem. Once there is blending, I get artifacts
      Just for the sake of just focussing on the shader side of things first, I upload the dual quaternions to GPU which are converted from regular matrices (because I knew they should work).
      Below an image comparison between matrix skinning (left) and dual quaternion skinning (right):

      As you can see, especially on the shoulders, there are some serious issues.
      It might be because of a silly typo however I'm surprised some parts of the mesh look perfectly fine.
      Below some snippets:
      //Blend bones float2x4 BlendBoneTransformsToDualQuaternion(float4 boneIndices, float4 boneWeights) { float2x4 dual = (float2x4)0; float4 dq0 = cSkinDualQuaternions[boneIndices.x][0]; for(int i = 0; i < MAX_BONES_PER_VERTEX; ++i) { if(boneIndices[i] == -1) { break; } if(dot(dq0, cSkinDualQuaternions[boneIndices[i]][0]) < 0) { boneWeights[i] *= -1; } dual += boneWeights[i] * cSkinDualQuaternions[boneIndices[i]]; } return dual / length(dual[0]); } //Used to transform the normal/tangent float3 QuaternionRotateVector(float3 v, float4 quatReal) { return v + 2.0f * cross(quatReal.xyz, quatReal.w * v + cross(quatReal.xyz, v)); } //Used to transform the position float3 DualQuatTransformPoint(float3 p, float4 quatReal, float4 quatDual) { float3 t = 2 * (quatReal.w * quatDual.xyz - quatDual.w * quatReal.xyz + cross(quatDual.xyz, quatReal.xyz)); return QuaternionRotateVector(p, quatReal) + t; } I've been staring at this for quite a while now so the solution might be obvious however I fail to see it.
      Help would be hugely appreciated  
    • By sevenfold1
      I'm looking for a open source PBR rendering engine that I can use.  Basic requirements are Windows (C/C++) and free to use type license.

      The first two hits I get on Google are:



      Does anybody have any experience using any of these, or do you recommend something else that's better?
      Pluses: Active development, easy to compile, zero dependencies.
    • By HappyCoder
      What is the game like
      I'm working on a game where the main mechanic is the player creates their own spells. They create spell using a sort of visual programming language
      Here is a diagram showing how the spell system would work

      The top spell would shoot fire out of the casters hand
      The second spell would shoot a projectile in a straight line until it hit something with no other effects
      The third spell would shoot a projectile and when it hits, explodes in a fireball
      Armed with only their knowledge of magic the player must navigate through caves and dungeons looking for artifacts and spells to allow them to become a master of the magic arts.
      What I have so far
      I prototype of the spell creation system. The user can draw symbols using an oculus touch controller in the air. The computer recognizes the symbol and the user can then move the symbols around to construct spells.
      List of spells I have working at the moment
      Fire - does damage, burns wood, and can light torches Wind - pushes objects and puts out torches Levitate - causes the target to become weightless, when used with wind you can push even heavy objects Light - a bright light used to light up dark areas What I need
      It would be great to have an artist to work with. I am going ahead doing the artwork on my own but having somebody who could take that too let me focus on the other aspects would be of great help
      I would also like if somebody would take on the role of designing levels. I think this game will rely on having many different interesting encounters to force them to come up with clever solutions to problems using their magic. It would be helpful to have somebody to collaborate with for ideas in the category and to focus on trying different levels out to help me focus on the programming.
    • By jb-dev
      This is a picture of a regular room. 
      Each rooms has a chance to have props with a certain layout.
      If a rock is spawn the player can try to break it by exploding it. These can spawn common collectibles like money and such...
      There are many different type of layout possible, including a totally random one.
      The generator simply picks a shape, an anchor position and the type of prop to be generated.
      The process itself is simply a 2D boolean array. We simply draw on that array like we would in a bitmap using traditional image manipulation algorithms.
      Once the array is set, then we simply add a given prop for each true cell of the array 
      We then finally remove every props that are either outside its room or obstructing an entry/exit point.
      Right now, only two types of props can be generated, although the algorithm itself is kinda flexible.

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!