Jumping
Blitz3D Forums/Blitz3D Beginners Area/Jumping
| ||
I know there are a number of posts addressing this already; however, I can't find them right now and am somewhat pressed for time. Before a player can jump, I need to check if the player is already jumping. I've found that EntityCollided() can work in certain situations, but it allows the player to jump up vertical surfaces. I remember seeing LinePick() used in the other posts about jumping back when I could find them, but thus far I havn't been able to get it to work (i.e. the player is no longer able to jump at all). This is the relevant bit of code: |
| ||
Not using Linepick but this is some jump code someone (sorry not sure who) posted on this forum. You will need to load your own map. |
| ||
Actually, it does use LinePick(). Regardless, it does not work, either. Thanks anyways. |
| ||
Heres a fix. so u dont have to load a level anymore: ;Simple Environment To Demonstrate One of Many Methods To Perform Collision Checking with Gravity ; ; Graphics3D 800,600,0,2 SetBuffer BackBuffer() Player=CreatePivot() ;Create a pivot for our player character, the camera will be parented to this Camera=CreateCamera() CameraRange camera,0.1,500 ;Adjust camera range to allow us to get 'close' to things. Experiment with this if you wish. EntityParent Camera,Player ;Attach the camera to the player pivot. This way the camera will move with the player and follow its orientation MoveEntity camera,0,0.2,0 ;Move the camera up slightly to place it at about eye level PositionEntity Player,12,25,-4 ;Place the player at an arbitrary location, in this case above the centre of the environment. ;Level=LoadAnimMesh("C:\Documents and Settings\john\Desktop\easybuilder\Easybuilder mk2\Exported\aliensmap\aliensmap.b3d") ;Load level mesh I've used loadanimmesh although could equally have used loadmesh Level = CreatePlane() EntityColor Level, 128, 128, 128 For x = 1 To Rnd(100) cube = CreateCube() PositionEntity cube, Rnd(x), 1, Rnd(x) Next EntityFX Level,1 ;Make the level full-bright AmbientLight 255,255,255 ;make the scene fully lit too! Const Gravity#=-.15 ;play around with this value, just don't make it positive (now let's see you resist that temptation). Const COLLISIONTYPE_SCENE = 1 ;define our collision types. This way we can classify easily what type of collision something needs Const COLLISIONTYPE_PLAYER = 2 Const PlayerCollisionRadius# = .150 ;this is the player's x-radius (horizontal). I've hardcoded the y-radius below, reason for doing ;this is that the normal human is not enclosed by a sphere but more by a cylindrical shape ;hence the y-radius will be longer than the x-radius. Const PlayerSpeed# = .075 ;How fast the player moves. Const PlayerJumpSpeed# = 2.0 EntityType Level,COLLISIONTYPE_SCENE,True ;set the collision types for our scene EntityType Player,COLLISIONTYPE_PLAYER ;and set it for the player EntityRadius Player,PlayerCollisionRadius,0.7 ;the 0.7 is the y-radius of the collision radius. Collisions COLLISIONTYPE_PLAYER,COLLISIONTYPE_SCENE,2,3 ;This command then sets the relationship for collisions between any object with collision type 'player' ;and any object with collision type 'scene' to 'ellipsoid to polygon' and 'slide upwards' RecursiveSearchMesh(Level);Set our level To pickable, specifically per polygon picking (inside this function...) ;this is not usually needed when using loadmesh, but with loadanimmesh there may be ;a hierarchy of meshes and so we need to parse through them all to set their entitypickmode, ;merely setting the entitypickmode of the entity handle "Level" may not give desired results. MoveMouse (GraphicsWidth()/2),GraphicsHeight()/2 ;Place the mouse in the centre of the screen/window. RubbishValue#=MouseXSpeed() ;These 'rubbish values' are designed to discard the mousex/yspeed() values which result RubbishValue#=MouseYSpeed() ;from moving the mouse back to the centre of the screen. Repeat TurnEntity Player,0,Float(MouseXSpeed())*-0.5,0 ;turn our player pivot around the vertical (y) axis when the player moves the mouse left/right TurnEntity Camera,Float(MouseYSpeed())*0.5,0,0 ;pitch our vision up/down when the mouse is moved up/down MoveMouse (GraphicsWidth()/2),GraphicsHeight()/2 ;reset the mouse position to the centre of the screen. RubbishValue#=MouseXSpeed() ;see comments from earlier above RubbishValue#=MouseYSpeed() ;see comments from earlier above LinePick EntityX(Player),EntityY(Player)-0.7,EntityZ(Player),0,-0.05,0,0 ;Look beneath the player's feet with a linepick If PickedEntity() = 0 Then PlayerOnGround=0 ;if the linepick hit something then we must be on the ground / able to walk around If PlayerOnGround = True Then ;If the player is on the ground, in contact with the surface then: MoveFWD=0 ;adjust the MoveForwards/MoveSideways variables back to zero in preparation for receiving new input from the player MoveRIGHT=0 JumpUP=0 If KeyDown(200) Then MoveFWD=15 ;if up arrow / cursor key pressed set the MoveForward flag to +1 If KeyDown(208) Then MoveFWD=-1 ;if down arrow / cursor key pressed set the MoveForward flag to -1 (backwards) If KeyDown(205) Then MoveRIGHT=1 ;if right arrow / cursor pressed set the MoveRight flag to +1 If KeyDown(203) Then MoveRIGHT=-1 ;if left arrow / cursor pressed set the MoveRight flag to -1 If MouseHit(1) Then JumpUp=1 ;if Left Mouse Button Clicked bar pressed then jump (assign a positive value to PlayerVelocityY) If PlayerVelocityY#<0 Then PlayerVelocityY#=0 ;as we are on the ground we need to ensure that we have no vertical velocity in the ;downwards direction. If JumpUp=1 Then ;if we are jumping (and only allows jumps when in contact with the ground) PlayerVelocityY = PlayerVelocityY + PlayerJumpSpeed EndIf If MoveFwd<>0 Or MoveRight<>0 Then ;if we have pressed a button to order the player to move then: TFormNormal MoveRIGHT,0,MoveFWD,Player,0 ;We need to transform our 'forwards' and 'sideways' direction from the player's local space into ;the direction in world space. We also want to convert the resultant vector into a 'unit vector' ;so that it represents direction only in order to simply scale the vector by the player's walk speed. PlayerVelocityX#=TFormedX()*PlayerSpeed PlayerVelocityZ#=TFormedZ()*PlayerSpeed Else PlayerVelocityX=0 ;no order to move pressed so set our horizontal velocity to zero. PlayervelocityZ=0 ;an alternative, if you want to have gradual slow down would be as follows: (comment out the two lines above first though) PlayerVelocityX=PlayerVelocityX*0.7 ;0.7 could be any number between 0 and 1, although I don't recommend using '1' as PlayerVelocityZ=PlayerVelocityZ*0.7 ;the player would always be moving. EndIf Else ;if the player is not on the ground then : ;Loop through the player's collisions with all other objects. If there is no collision or there is a collision with ;a surface that is too steep then allow the player's vertical velocity to keep increasing in the negative direction. For ColIndex=1 To CountCollisions(Player) If CollisionNY(Player,ColIndex)>0.7 Then PlayerOnGround=True:PlayerVelocityY#=0 : Exit ;if the collision between the player and the other object is such that the surface collided with has a normal vector ;pointing upwards at more than 45 degrees relative to the horizontal, (if the surface was flat collisionNY would return 1.0 ;which corresponds to a normal vector pointing upwards at 90 degrees to the horizontal) - then set their 'on ground' flag ;to 1, and set their vertical velocity back to zero. Next EndIf PlayerVelocityY#=PlayerVelocityY#+Gravity# ;Gravity acts upon the player's velocity each frame, even if on the ground - although ;if on ground the collision detection will prevent the player falling through the floor. TranslateEntity Player,PlayerVelocityX,PlayerVelocityY,PlayerVelocityZ ;move the player a distance equal to their velocities in ;each of the 3 directions x/y/z. UpdateWorld ;standard blitz command, collision checks are all performed here, and animation. RenderWorld ;render the environment. Repeat ;delay the program for a small amount of time Delay 1 Until Abs(FrameTime-MilliSecs())>15 Text 10,10,playeronground Flip ;flip the backbuffer() into view. FrameTime=MilliSecs() ;really simple frame limiting, for an example of better timing look elsewhere, it is not covered here. Until KeyDown(1) ;ESCAPE FreeEntity level ;always good to free any entities when finished with them FreeEntity camera FreeEntity player End ;end of program. ;Recursive Routine which is used to set the pick mode of meshes which are children of the root node. Function RecursiveSearchMesh(Mesh) If CountChildren(Mesh) = 0 And EntityClass(Mesh) = "Mesh" Then EntityPickMode Mesh,2 For C=1 To CountChildren(Mesh) Child=GetChild(Mesh,C) If EntityClass(Child)="Mesh" Then EntityPickMode Child,2 RecursiveSearchMesh(Child) Next End Function Jump still does not work. can somebody plz help fix this? ANY help is GREATLY appreciated! :) ~DS~ |
| ||
Hey Owl, why are you only using LinePick IF the user presses space? you should be checking it everytime. That result is if the character is on the ground or not. From then on, based on that result, you allow him to jump if the user presses space. |
| ||
Kryzon: Very good question. However, it still doesn't work, even when I move LinePick. This is what the code looks like now: |
| ||
LinePick(EntityX(p\entity),EntityY(p\entity),EntityZ(p\entity),0,1,0) Why are you checking above you? LinePick(EntityX(p\entity),EntityY(p\entity),EntityZ(p\entity),0,-1,0) ;or LinePick(EntityX(p\entity),EntityY(p\entity),EntityZ(p\entity),0,-((MeshHeight(p\entity)/2)+.2),0) |
| ||
I was messing with the code to see if maybe that would work and forgot to set it back. Changing it to -1 doesn't make it work, though. |
| ||
ur right. didnt work. heres the code i have so far man: ;Simple Environment To Demonstrate One of Many Methods To Perform Collision Checking with Gravity ; ; Graphics3D 800,600,0,2 SetBuffer BackBuffer() Player=CreatePivot() ;Create a pivot for our player character, the camera will be parented to this Camera=CreateCamera() CameraRange camera,0.1,500 ;Adjust camera range to allow us to get 'close' to things. Experiment with this if you wish. EntityParent Camera,Player ;Attach the camera to the player pivot. This way the camera will move with the player and follow its orientation MoveEntity camera,0,0.2,0 ;Move the camera up slightly to place it at about eye level PositionEntity Player,12,25,-4 ;Place the player at an arbitrary location, in this case above the centre of the environment. ;Level=LoadAnimMesh("C:\Documents and Settings\john\Desktop\easybuilder\Easybuilder mk2\Exported\aliensmap\aliensmap.b3d") ;Load level mesh I've used loadanimmesh although could equally have used loadmesh Level = CreatePlane() EntityColor Level, 128, 128, 128 For x = 1 To Rnd(100) cube = CreateCube() PositionEntity cube, Rnd(x), 1, Rnd(x) Next EntityFX Level,1 ;Make the level full-bright AmbientLight 255,255,255 ;make the scene fully lit too! Const Gravity#=-.15 ;play around with this value, just don't make it positive (now let's see you resist that temptation). Const COLLISIONTYPE_SCENE = 1 ;define our collision types. This way we can classify easily what type of collision something needs Const COLLISIONTYPE_PLAYER = 2 Const PlayerCollisionRadius# = .150 ;this is the player's x-radius (horizontal). I've hardcoded the y-radius below, reason for doing ;this is that the normal human is not enclosed by a sphere but more by a cylindrical shape ;hence the y-radius will be longer than the x-radius. Const PlayerSpeed# = .075 ;How fast the player moves. Const PlayerJumpSpeed# = 2.0 EntityType Level,COLLISIONTYPE_SCENE,True ;set the collision types for our scene EntityType Player,COLLISIONTYPE_PLAYER ;and set it for the player EntityRadius Player,PlayerCollisionRadius,0.7 ;the 0.7 is the y-radius of the collision radius. Collisions COLLISIONTYPE_PLAYER,COLLISIONTYPE_SCENE,2,3 ;This command then sets the relationship for collisions between any object with collision type 'player' ;and any object with collision type 'scene' to 'ellipsoid to polygon' and 'slide upwards' RecursiveSearchMesh(Level);Set our level To pickable, specifically per polygon picking (inside this function...) ;this is not usually needed when using loadmesh, but with loadanimmesh there may be ;a hierarchy of meshes and so we need to parse through them all to set their entitypickmode, ;merely setting the entitypickmode of the entity handle "Level" may not give desired results. MoveMouse (GraphicsWidth()/2),GraphicsHeight()/2 ;Place the mouse in the centre of the screen/window. RubbishValue#=MouseXSpeed() ;These 'rubbish values' are designed to discard the mousex/yspeed() values which result RubbishValue#=MouseYSpeed() ;from moving the mouse back to the centre of the screen. Repeat TurnEntity Player,0,Float(MouseXSpeed())*-0.5,0 ;turn our player pivot around the vertical (y) axis when the player moves the mouse left/right TurnEntity Camera,Float(MouseYSpeed())*0.5,0,0 ;pitch our vision up/down when the mouse is moved up/down MoveMouse (GraphicsWidth()/2),GraphicsHeight()/2 ;reset the mouse position to the centre of the screen. RubbishValue#=MouseXSpeed() ;see comments from earlier above RubbishValue#=MouseYSpeed() ;see comments from earlier above ; LinePick EntityX(Player),EntityY(Player)-0.7,EntityZ(Player),0,-0.05,0,0 ;Look beneath the player's feet with a linepick LinePick(EntityX(Player),EntityY(Player),EntityZ(Player),0,-((MeshHeight(Player)/2)+.2),0) If PickedEntity() = 0 Then PlayerOnGround=0 ;if the linepick hit something then we must be on the ground / able to walk around If PlayerOnGround = True Then ;If the player is on the ground, in contact with the surface then: MoveFWD=0 ;adjust the MoveForwards/MoveSideways variables back to zero in preparation for receiving new input from the player MoveRIGHT=0 JumpUP=0 If KeyDown(200) Then MoveFWD=15 ;if up arrow / cursor key pressed set the MoveForward flag to +1 If KeyDown(208) Then MoveFWD=-1 ;if down arrow / cursor key pressed set the MoveForward flag to -1 (backwards) If KeyDown(205) Then MoveRIGHT=1 ;if right arrow / cursor pressed set the MoveRight flag to +1 If KeyDown(203) Then MoveRIGHT=-1 ;if left arrow / cursor pressed set the MoveRight flag to -1 If MouseHit(1) Then JumpUp=1 ;if Left Mouse Button Clicked bar pressed then jump (assign a positive value to PlayerVelocityY) If PlayerVelocityY#<0 Then PlayerVelocityY#=0 ;as we are on the ground we need to ensure that we have no vertical velocity in the ;downwards direction. If JumpUp=1 Then ;if we are jumping (and only allows jumps when in contact with the ground) PlayerVelocityY = PlayerVelocityY + PlayerJumpSpeed EndIf If MoveFwd<>0 Or MoveRight<>0 Then ;if we have pressed a button to order the player to move then: TFormNormal MoveRIGHT,0,MoveFWD,Player,0 ;We need to transform our 'forwards' and 'sideways' direction from the player's local space into ;the direction in world space. We also want to convert the resultant vector into a 'unit vector' ;so that it represents direction only in order to simply scale the vector by the player's walk speed. PlayerVelocityX#=TFormedX()*PlayerSpeed PlayerVelocityZ#=TFormedZ()*PlayerSpeed Else PlayerVelocityX=0 ;no order to move pressed so set our horizontal velocity to zero. PlayervelocityZ=0 ;an alternative, if you want to have gradual slow down would be as follows: (comment out the two lines above first though) PlayerVelocityX=PlayerVelocityX*0.7 ;0.7 could be any number between 0 and 1, although I don't recommend using '1' as PlayerVelocityZ=PlayerVelocityZ*0.7 ;the player would always be moving. EndIf Else ;if the player is not on the ground then : ;Loop through the player's collisions with all other objects. If there is no collision or there is a collision with ;a surface that is too steep then allow the player's vertical velocity to keep increasing in the negative direction. For ColIndex=1 To CountCollisions(Player) If CollisionNY(Player,ColIndex)>0.7 Then PlayerOnGround=True:PlayerVelocityY#=0 : Exit ;if the collision between the player and the other object is such that the surface collided with has a normal vector ;pointing upwards at more than 45 degrees relative to the horizontal, (if the surface was flat collisionNY would return 1.0 ;which corresponds to a normal vector pointing upwards at 90 degrees to the horizontal) - then set their 'on ground' flag ;to 1, and set their vertical velocity back to zero. Next EndIf PlayerVelocityY#=PlayerVelocityY#+Gravity# ;Gravity acts upon the player's velocity each frame, even if on the ground - although ;if on ground the collision detection will prevent the player falling through the floor. TranslateEntity Player,PlayerVelocityX,PlayerVelocityY,PlayerVelocityZ ;move the player a distance equal to their velocities in ;each of the 3 directions x/y/z. UpdateWorld ;standard blitz command, collision checks are all performed here, and animation. RenderWorld ;render the environment. Repeat ;delay the program for a small amount of time Delay 1 Until Abs(FrameTime-MilliSecs())>15 Text 10,10,playeronground Flip ;flip the backbuffer() into view. FrameTime=MilliSecs() ;really simple frame limiting, for an example of better timing look elsewhere, it is not covered here. Until KeyDown(1) ;ESCAPE FreeEntity level ;always good to free any entities when finished with them FreeEntity camera FreeEntity player End ;end of program. ;Recursive Routine which is used to set the pick mode of meshes which are children of the root node. Function RecursiveSearchMesh(Mesh) If CountChildren(Mesh) = 0 And EntityClass(Mesh) = "Mesh" Then EntityPickMode Mesh,2 For C=1 To CountChildren(Mesh) Child=GetChild(Mesh,C) If EntityClass(Child)="Mesh" Then EntityPickMode Child,2 RecursiveSearchMesh(Child) Next End Function |
| ||
Look Owl (you mind if I call you Owl?), based on your most recent snippet I'll re-write it the way I think it should be:[...] ;You're gonna have to tweak the LinePick's -Y value just so it's perfect for the feet of the character. Anything more than that will make him stop while in the air. If p\jump = 1 MoveEntity p\entity,0,p\yVel#,0 p\yVel# = p\yVel# - 0.1 If p\yVel < 0 Then LinePick(EntityX(p\entity,1),EntityY(p\entity,1),EntityZ(p\entity,1),0,-2,0) If PickedEntity() <> 0 Then Jump = 0 Else LinePick(EntityX(p\entity,1),EntityY(p\entity,1),EntityZ(p\entity,1),0,-2,0) If PickedEntity() <> 0 And KeyHit(SPACEBAR) Then p\yVel# = 2 p\jump = 1 EndIf Endif Changed the numbers "signs" too (can't remember the name in english). You don't need them to be negative. I hope it works! EDIT: It was wrong, now I corrected it =X |
| ||
You can call me Owl. I don't mind. It still doesn't work, but thanks. |
| ||
Corrected it. It was logically faulty, the character didn't have the chance to get back on ground and turn off the jump. |
| ||
Still nothing... |
| ||
I will check when I get home but the original code works for me. LMB for jump. Just checked but works fine with mouse button to jump. |
| ||
I still can't get it to work. It looks like the problem is with LinePick(); no matter what I try, I can't get it 'pick' an entity. Has anyone else come up with something? Edit: Disregard that! Predictably, I figured out how to fix it right after I posted. Edit 2: Is there a way to get LinePick() to check against an entire mesh and not just its handle? |
| ||
Then you need to set EntityPickMode for each child entity:function Recursive_EntityPickMode(ent, mode) EntityPickMode ent, mode for i = 1 to countchildren(ent) Recursive_EntityPickMode(getchild(ent,i), mode) next end function |
| ||
Thanks! |