AnthonyPython Posted February 18, 2015 Share Posted February 18, 2015 I was wondering how would this be done to detect edges and allow the player to jump and grab edges then lift them selves up. Quote OS: Windows 10 Pro CPU: i3-10100 CPU @ 3.60GHz GPU: NVIDIA 2060 Super - 8 GB RAM: 32 GB Link to comment Share on other sites More sharing options...
gamedeviancy Posted February 18, 2015 Share Posted February 18, 2015 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. 1 Quote "The only true wisdom is in knowing you know nothing." ~ Socrates Link to comment Share on other sites More sharing options...
Olby Posted February 18, 2015 Share Posted February 18, 2015 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. 2 Quote Intel Core i7 Quad 2.3 Ghz, 8GB RAM, GeForce GT 630M 2GB, Windows 10 (x64) Link to comment Share on other sites More sharing options...
AnthonyPython Posted February 18, 2015 Author Share Posted February 18, 2015 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 Quote OS: Windows 10 Pro CPU: i3-10100 CPU @ 3.60GHz GPU: NVIDIA 2060 Super - 8 GB RAM: 32 GB Link to comment Share on other sites More sharing options...
gamecreator Posted February 18, 2015 Share Posted February 18, 2015 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. Quote Link to comment Share on other sites More sharing options...
Olby Posted February 18, 2015 Share Posted February 18, 2015 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 [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.) 1 Quote Intel Core i7 Quad 2.3 Ghz, 8GB RAM, GeForce GT 630M 2GB, Windows 10 (x64) Link to comment Share on other sites More sharing options...
Rick Posted February 18, 2015 Share Posted February 18, 2015 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. 1 Quote Link to comment Share on other sites More sharing options...
AnthonyPython Posted February 18, 2015 Author Share Posted February 18, 2015 This is some great Info guys thanks 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 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. 1 Quote OS: Windows 10 Pro CPU: i3-10100 CPU @ 3.60GHz GPU: NVIDIA 2060 Super - 8 GB RAM: 32 GB Link to comment Share on other sites More sharing options...
AnthonyPython Posted February 19, 2015 Author Share Posted February 19, 2015 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 Quote OS: Windows 10 Pro CPU: i3-10100 CPU @ 3.60GHz GPU: NVIDIA 2060 Super - 8 GB RAM: 32 GB Link to comment Share on other sites More sharing options...
AnthonyPython Posted February 20, 2015 Author Share Posted February 20, 2015 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? Quote OS: Windows 10 Pro CPU: i3-10100 CPU @ 3.60GHz GPU: NVIDIA 2060 Super - 8 GB RAM: 32 GB Link to comment Share on other sites More sharing options...
Rick Posted February 20, 2015 Share Posted February 20, 2015 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. Quote Link to comment Share on other sites More sharing options...
AnthonyPython Posted February 20, 2015 Author Share Posted February 20, 2015 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 Quote OS: Windows 10 Pro CPU: i3-10100 CPU @ 3.60GHz GPU: NVIDIA 2060 Super - 8 GB RAM: 32 GB Link to comment Share on other sites More sharing options...
Rick Posted February 20, 2015 Share Posted February 20, 2015 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. Quote Link to comment Share on other sites More sharing options...
AnthonyPython Posted February 20, 2015 Author Share Posted February 20, 2015 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) Quote OS: Windows 10 Pro CPU: i3-10100 CPU @ 3.60GHz GPU: NVIDIA 2060 Super - 8 GB RAM: 32 GB Link to comment Share on other sites More sharing options...
nick.ace Posted February 20, 2015 Share Posted February 20, 2015 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: Quote Link to comment Share on other sites More sharing options...
AnthonyPython Posted February 20, 2015 Author Share Posted February 20, 2015 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 also that is very nice of you to do that nick. 1 Quote OS: Windows 10 Pro CPU: i3-10100 CPU @ 3.60GHz GPU: NVIDIA 2060 Super - 8 GB RAM: 32 GB Link to comment Share on other sites More sharing options...
AnthonyPython Posted February 20, 2015 Author Share Posted February 20, 2015 Also, for inspiration: dat parkour Quote OS: Windows 10 Pro CPU: i3-10100 CPU @ 3.60GHz GPU: NVIDIA 2060 Super - 8 GB RAM: 32 GB Link to comment Share on other sites More sharing options...
nick.ace Posted February 20, 2015 Share Posted February 20, 2015 Thanks for teaching me this info also that is very nice of you to do that nick. 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... 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.