Jump to content

parkour


AnthonyPython
 Share

Recommended Posts

Well if you want an example of how not to do it, just play Dying Light. I really want to like this game, as there aren't many 3d games on Linux, but I just can't seem to enjoy it. The 'parkour' in this game is rather stupid, and it only shines when you break from the immersion of the open world to solve an asinine puzzle like climbing some antenna towers.

 

About the only thing I like about the parkour element of the game so far is that I can run up and jump off the zombies themselves. Something like parkour really needs to be an element of the game that is fun, not just something you can do on some side buildings and something you're forced to do in a ridiculous manner to finish a quest.

  • Upvote 1

"The only true wisdom is in knowing you know nothing." ~ Socrates

Link to comment
Share on other sites

The easiest solution would likely involve invisible CSG trigger zones. Once collided with and if player is in upwards jumping motion initiate the climbing action. Depending on the size of your levels this might not be an option.

 

Another way I can think of is to detect climbable edges procedurally. When jump action is fired shoot a ray ahead of the player (at foot level). If it collides at a reasonable distance with a wall then trace it upwards until there is an edge which is at least 45+ degrees perpendicular to the wall. This gives an indication of a usable surface for climbing. Along with other checks this can be developed into a sophisticated system for the sort of actions you want.

  • Upvote 2

Intel Core i7 Quad 2.3 Ghz, 8GB RAM, GeForce GT 630M 2GB, Windows 10 (x64)

Link to comment
Share on other sites

Well if you want an example of how not to do it, just play Dying Light. I really want to like this game, as there aren't many 3d games on Linux, but I just can't seem to enjoy it. The 'parkour' in this game is rather stupid, and it only shines when you break from the immersion of the open world to solve an asinine puzzle like climbing some antenna towers.

 

About the only thing I like about the parkour element of the game so far is that I can run up and jump off the zombies themselves. Something like parkour really needs to be an element of the game that is fun, not just something you can do on some side buildings and something you're forced to do in a ridiculous manner to finish a quest.

 

don't worry parkour in my game will be a element in which the player is going to use quite a lot.

 

The easiest solution would likely involve invisible CSG trigger zones. Once collided with and if player is in upwards jumping motion initiate the climbing action. Depending on the size of your levels this might not be an option.

 

Another way I can think of is to detect climbable edges procedurally. When jump action is fired shoot a ray ahead of the player (at foot level). If it collides at a reasonable distance with a wall then trace it upwards until there is an edge which is at least 45+ degrees perpendicular to the wall. This gives an indication of a usable surface for climbing. Along with other checks this can be developed into a sophisticated system for the sort of actions you want.

 

how do I check if the edge is at least 45 degree's and is perpendicular? could you give me an example

OS: Windows 7

Processor: AMD A6-3420M APU integrated Radeon HD Graphics 1.50 GHz

Link to comment
Share on other sites

how do I check if the edge is at least 45 degree's and is perpendicular? could you give me an example

When you use the Pick function it will return PickInfo which should have all the information you need.

 

I think the harder part would be to trace the wall upwards. Not sure exactly how that would be done. Continuous picks seem expensive but maybe you can use surface/vertex data somehow.

Link to comment
Share on other sites

I haven't had the need to do this myself so this is just all theory. But the assumption is if you pick what's in front of the player and get the pickInfo in return (http://www.leadwerks.com/werkspace/page/documentation/_/command-reference/pickinfo/) you will be able to get the normal of a surface. If you do the same for the adjacent plane and compare the two this will lead you to determining the angle between the two surfaces. This is complex stuff, so investigate this only if you really need to have full freedom to climb any wall without the necessity to hard-code the spots smile.png

 

[Edit] As for tracing the wall upwards. It can be done by offsetting the initial ray by half-height of the player. And repeating the pick a few times until the max jump height is reached i.e. player cant reach the ledge any more.

 

Perhaps this drawing can explain it better. At most you will have to trace 6-8 short rays and based on which of those are blocked you can perform different actions (tall obstacles, low obstacles etc.)

 

post-4357-0-38377300-1424281275_thumb.jpg

  • Upvote 1

Intel Core i7 Quad 2.3 Ghz, 8GB RAM, GeForce GT 630M 2GB, Windows 10 (x64)

Link to comment
Share on other sites

When you jump do 2 raycasts only at certain distances in "front" of the player. 1 around the shoulder height of the character (play around with this height) and another at the feet. If the shoulder one doesn't hit anything AND the feet one does that means you are jumping at an edge area. If you are also moving forward, then do the parkour thing.

  • Upvote 1
Link to comment
Share on other sites

This is some great Info guys thanks biggrin.png

 

This is complex stuff, so investigate this only if you really need to have full freedom to climb any wall without the necessity to hard-code the spots smile.png

 

 

I'd rather have this instead of hard-coding them, and I love complex stuff, so this will be a valuable thing to learn and do for me.

  • Upvote 1

OS: Windows 7

Processor: AMD A6-3420M APU integrated Radeon HD Graphics 1.50 GHz

Link to comment
Share on other sites

This is what I have so far, if there is something being used incorrectly of something or something isn't right let me know.

Script.target = "" --entity "target"
Script.Range = 2.0 --float "Range"
Script.MinNormal = 45 --float "Min Normal"
Script.MaxNormal = 120 --float "Max Normal"
function Script:Start()

end
function Script:UpdateWorld()
local pickInfo = PickInfo()

local castPos = pickInfo.position
local NormalInfo = pickInfo.normal
local playerPos = self.target:GetPosition(true)

System:Print(castPos:DistanceToPoint(playerPos) <= self.Range)
--Is the player within the range?


if(castPos:DistanceToPoint(playerPos) <= self.Range) then


 local point2 = Transform:Point(0,0,self.Range, self.entity, nil)

  if(self.entity.world:Pick(castPos, point2, pickInfo, 0, true)) then
   if (NormalInfo >= MinNormal and NormalInfo <= MaxNormal) then

 --set or call something here.

   end
  end
end

end

OS: Windows 7

Processor: AMD A6-3420M APU integrated Radeon HD Graphics 1.50 GHz

Link to comment
Share on other sites

it's not giving any error's or anything not sure why it's not printing out, I must be doing something wrong, I know I am close enough, not sure about the normal's part if it is even detecting the object's,

Script.target = "" --entity "target"
Script.Range = 2.0 --float "Range"
Script.MinNormal = 45 --float "Min Normal"
Script.MaxNormal = 120 --float "Max Normal"
function Script:Start()

end
function Script:UpdateWorld()
local window = Window:GetCurrent()
local pickInfo = PickInfo()
local castPos = pickInfo.position
local playerPos = self.target:GetPosition(true)

--System:Print(string(castPos:DistanceToPoint(playerPos) <= self.Range))
--Is the player within the range?


if(castPos:DistanceToPoint(playerPos) <= self.Range) then

if(window:KeyDown(Key.Space)) then



local NormalInfo = pickInfo.normal
local point2 = Transform:Point(0,0,self.Range, self.entity, nil)


if(self.entity.world:Pick(castPos, point2, pickInfo, 0, true)) then
 if (NormalInfo >= MinNormal and NormalInfo <= MaxNormal) then

 System:Print("Dected proper")
 --set or call something here.

 end
end end
end

end

 

Thought's?

OS: Windows 7

Processor: AMD A6-3420M APU integrated Radeon HD Graphics 1.50 GHz

Link to comment
Share on other sites

local pickInfo = PickInfo()

local castPos = pickInfo.position

 

if(castPos:DistanceToPoint(playerPos) <= self.Range) then

 

 

What is castPos? Normally you do a Pick passing in the pickinfo. That pick fills in the pickinfo variable and then you use the filled in variables. You aren't calling a Pick before you use pickInfo.position means nothing is filling position in with anything of value.

Link to comment
Share on other sites

local pickInfo = PickInfo()

local castPos = pickInfo.position

 

if(castPos:DistanceToPoint(playerPos) <= self.Range) then

 

 

What is castPos? Normally you do a Pick passing in the pickinfo. That pick fills in the pickinfo variable and then you use the filled in variables. You aren't calling a Pick before you use pickInfo.position means nothing is filling position in with anything of value.

 

updated:

Script.target = "" --entity "target"
Script.Range = 2.0 --float "Range"
Script.PickRange = 0.2 --float "Range"
Script.MinNormal = 45 --float "Min Normal"
Script.MaxNormal = 120 --float "Max Normal"
function Script:Start()

end
function Script:UpdateWorld()
local point2 = Transform:Point(0,0,self.PickRange, self.entity, nil)
local pickInfo = PickInfo()
local castPos

self.entity.world:Pick(self.entity:GetPosition(), point2, pickInfo, 0, true)

local window = Window:GetCurrent()
--local pickInfo = PickInfo()
castPos = pickInfo.position
local playerPos = self.target:GetPosition(true)


System:Print(castPos)
--Is the player within the range?


if(castPos:DistanceToPoint(playerPos) <= self.Range) then

 if(window:KeyDown(Key.Space)) then



  local NormalInfo = pickInfo.normal




   if (NormalInfo >= MinNormal and NormalInfo <= MaxNormal) then

 System:Print("Dected proper")
 --set or call something here.

   end
 end
end

end

 

did a system print with castPos just printing out zero's

OS: Windows 7

Processor: AMD A6-3420M APU integrated Radeon HD Graphics 1.50 GHz

Link to comment
Share on other sites

You always want to check that Pick returned true (since it returns true if it actually picked something and false otherwise). http://www.leadwerks.com/werkspace/page/documentation/_/command-reference/world/worldpick-r502

 

Are you walking up to a wall?

 

Note that generally the GetPosition() of a character model will return it's feet position which may be too close to the ground. Store that off in a Vec3 and add a little to the y so it moves up. Also do the same +y to the 2nd point.

 

If all else fails make 2 small cubes in Start() and always position those at the 2 points you are testing so you can visually see the start and end of the raycast. Just hide() these cubes at the start of Update() and show then again at the end so they don't get picked.

 

Make your radius value different than 0 maybe?

 

Play around with the last parameter (collision type). This will be the collision value for this ray, which means it'll adhere to this chart about collide or not (http://www.leadwerks.com/werkspace/page/documentation/_/command-reference/collision-r778)

 

The default value is 0, which I would think is None, which I wouldn't think would collide with anything but I could be wrong on that. I generally specify something there.

Link to comment
Share on other sites

You always want to check that Pick returned true (since it returns true if it actually picked something and false otherwise). http://www.leadwerks.com/werkspace/page/documentation/_/command-reference/world/worldpick-r502

 

Are you walking up to a wall?

 

Note that generally the GetPosition() of a character model will return it's feet position which may be too close to the ground. Store that off in a Vec3 and add a little to the y so it moves up. Also do the same +y to the 2nd point.

 

If all else fails make 2 small cubes in Start() and always position those at the 2 points you are testing so you can visually see the start and end of the raycast. Just hide() these cubes at the start of Update() and show then again at the end so they don't get picked.

 

Make your radius value different than 0 maybe?

 

Play around with the last parameter (collision type). This will be the collision value for this ray, which means it'll adhere to this chart about collide or not (http://www.leadwerks.com/werkspace/page/documentation/_/command-reference/collision-r778)

 

The default value is 0, which I would think is None, which I wouldn't think would collide with anything but I could be wrong on that. I generally specify something there.

 

not using the character right now, using a pivot currently, I changed the collision to Scene, and at one point it did pick something up. I might have it to high, playing around with it

 

Edit: Ok , changed it to Projectile to detect only Scene, and prop stuff, I seem to be getting a bunch of correct feed back right now. got a( trying to compare a nil value with)

 (NormalInfo >= MinNormal and NormalInfo <= MaxNormal)

OS: Windows 7

Processor: AMD A6-3420M APU integrated Radeon HD Graphics 1.50 GHz

Link to comment
Share on other sites

A few things:

 

Don't do this:

castPos = pickInfo.position

 

Picks are expensive, especially when you always call the closest point. Not only that, but you have to do an extra comparison anyway. Instead, use a transform for "near point."

 

Secondly, the normal returned from the PickInfo() object is a Vec3, not a float.

 

Do this instead:

 

0 * ---- *

-|- * -- *

/ \

 

where * are transforms (and that's supposed to be a person on the left). Do two picks instead of one between the two transforms. Note that the distance is different between the two, which will allow you to simulate an angle.

 

Since you didn't get a runtime error from the incorrect comparison, that means that your transform is likely WAY too small. You should multiply the range by about 100.

 

Your thread inspired me to change the FPSPlayer.lua script to have a simple parkour system when sprinting. I'll post it on the workshop.

 

Also, for inspiration:

Link to comment
Share on other sites

A few things:

 

Don't do this:

castPos = pickInfo.position

 

Picks are expensive, especially when you always call the closest point. Not only that, but you have to do an extra comparison anyway. Instead, use a transform for "far point."

 

Secondly, the normal returned from the PickInfo() object is a Vec3, not a float.

 

Do this instead:

 

0 * ---- *

-|- * -- *

/ \

where * are transforms. Do two picks instead of one between the two transforms. Note that the distance is different between the two, which will allow you to simulate an angle.

 

 

I'm actually surprised you didn't get a runtime error, so that means...

Your transform is WAY too small. You should multiply the range by about 100.

 

Your thread inspired me to change the FPSPlayer.lua script to have a simple parkour system when sprinting. I'll post it on the workshop.

 

Also, for inspiration:

 

Thanks for teaching me this info tongue.png also that is very nice of you to do that nick.cool.png

  • Upvote 1

OS: Windows 7

Processor: AMD A6-3420M APU integrated Radeon HD Graphics 1.50 GHz

Link to comment
Share on other sites

Thanks for teaching me this info tongue.png also that is very nice of you to do that nick.cool.png

 

np! it should be up. I modified only the UpdatePhysics(). IDK how to use the workshop now, so it extracts to the root folder. I'll see if I can fix it though.

 

I commented some code, but it should be fairly self-explanatory. I keep it to like 9 lines I think? Anyway, the only changes are at the top of the UpdatePhysics() section where those 4 points are defined (and redefined) and in the KeyDown() SHIFT conditional.

 

Also, you'll notice that the bottom check is not actually at the bottom of the character. That would generally be a bad idea. It should be around two feet above the character's feet since that's where the character controller ends (mine might not be though). Basically, all I have now is automatic climb/jump on small ledges, so it's very simple.

 

Edit: It's at least in the Addons/Addons/Parkour folder now, I give up trying to make the correct directory...

  • Upvote 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...