I have made a character controller and would like some help perfecting it.
When you jump it descends slowly to the ground. I have no clue how to fix this. I tried to increase the gravity, but jitters when on the ground. I also tried speeding up the simulation, but that doesn't speed up the descent my much.
Here is the code:
Phy Start
Phy Set Auto Fixed Timing
AutoCam Off
Sync On : Sync Rate 60
GoSub Define_CharacterController
` Setup Level
Make Object Box 1000, 1000, 1, 1000
Phy Make Rigid Body Static Box 1000
MakeCharacterController(100, 11, 100, 20, 1000, 2000, 10000)
Do
UpdateCharacterController()
Phy Update
Sync
Loop
Define_CharacterController:
Type CharacterKeys
Up
Down
Right
Left
Run
Jump
EndType
Global DefaultKeys As CharacterKeys
DefaultKeys.Up = 17
DefaultKeys.Down = 31
DefaultKeys.Right = 32
DefaultKeys.Left = 30
DefaultKeys.Run = 42
DefaultKeys.Jump = 57
Type Character
ControlObjectIndex
DynamicObjectIndex
LookSpeed#
WalkSpeed#
RunSpeed#
Keys As CharacterKeys
CanJump
JumpSpeed#
CurrentJumpSpeed#
OldCamAngleX#
OldCamAngleY#
CameraAngleX#
CameraAngleY#
EndType
Global Player As Character
Global ObjectCount : ObjectCount = Object Count()
Phy Make Material 1, "Character"
Phy Set Material Restitution 1, 0.0
Phy Set Material Dynamic Friction 1, 0.1
Phy Set Material Static Friction 1, 0.1
Phy Build Material 1
Return
Function MakeCharacterController(X#, Y#, Z#, Size#, WalkSpeed#, RunSpeed#, JumpSpeed#)
Player.ControlObjectIndex = NextObject()
Make Object Sphere Player.ControlObjectIndex, Size#
Position Object Player.ControlObjectIndex, X#, Y#, Z#
Player.DynamicObjectIndex = NextObject()
Make Object Sphere Player.DynamicObjectIndex, Size#
Position Object Player.DynamicObjectIndex, X#, Y#, Z#
Phy Make Rigid Body Dynamic Sphere Player.DynamicObjectIndex, 1 ` Character Material
`Phy Set Rigid Body Mass Player.DynamicObjectIndex, 10
Player.Keys = DefaultKeys
Player.LookSpeed# = 0.4
Player.JumpSpeed# = JumpSpeed#
Player.WalkSpeed# = WalkSpeed#
Player.RunSpeed# = RunSpeed#
EndFunction
Function SetCharacterPosition(X#, Y#, Z#)
`Position Object Player.ControlObjectIndex, X#, Y#, Z#
Phy Set Rigid Body Position Player.DynamicObjectIndex, X#, Y#, Z#
EndFunction
Function SetCharacterRotation(X#, Y#, Z#)
`Rotate Object Player.ControlObjectIndex, X#, Y#, Z#
Phy Set Rigid Body Rotation Player.DynamicObjectIndex, X#, Y#, Z#
EndFunction
Function SetCharacterLookSpeed(Speed#)
Player.LookSpeed# = Speed#
EndFunction
Function UpdateCharacterController()
Position Camera Object Position X(Player.DynamicObjectIndex), Object Position Y(Player.DynamicObjectIndex), Object Position Z(Player.DynamicObjectIndex)
YRotate Camera WrapValue(Camera Angle Y() + MouseMoveX())
XRotate Camera WrapValue(Camera Angle X() + MouseMoveY())
Move Camera Up 15
If KeyState(Player.Keys.Run) = 1
Speed# = Player.RunSpeed#
Else
Speed# = Player.WalkSpeed#
EndIf
If KeyState(Player.Keys.Left) = 1
Phy Add Rigid Body Local Force Player.DynamicObjectIndex, -Speed#, 0, 0, 5
EndIf
If KeyState(Player.Keys.Right) = 1
Phy Add Rigid Body Local Force Player.DynamicObjectIndex, Speed#, 0, 0, 5
EndIf
If KeyState(Player.Keys.Up) = 1
Phy Add Rigid Body Local Force Player.DynamicObjectIndex, 0, 0, Speed#, 5
EndIf
If KeyState(Player.Keys.Down) = 1
Phy Add Rigid Body Local Force Player.DynamicObjectIndex, 0, 0, -Speed#, 5
EndIf
If KeyState(Player.Keys.Jump) = 1 and Player.CanJump = 0
Player.CanJump = 1
Phy Add Rigid Body Force Player.DynamicObjectIndex, 0, Player.JumpSpeed#, 0, 5
`Phy Set Rigid Body Angular Velocity Player.DynamicObjectIndex, 0, Player.CurrentJumpSpeed#, 0
EndIf
Phy Set Rigid Body Linear Momentum Player.DynamicObjectIndex, 0.0, Phy Get Rigid Body Linear Momentum Y(Player.DynamicObjectIndex), 0.0
Phy Set Rigid Body Angular Velocity Player.DynamicObjectIndex, 0.0, Phy Get Rigid Body Angular Velocity Y(Player.DynamicObjectIndex), 0.0
Phy Set Rigid Body Rotation Player.DynamicObjectIndex, 0.0, Camera Angle Y(), 0.0
Position Object Player.ControlObjectIndex, Object Position X(Player.DynamicObjectIndex), Object Position Y(Player.DynamicObjectIndex), Object Position Z(Player.DynamicObjectIndex)
Rotate Object Player.ControlObjectIndex, Object Angle X(Player.DynamicObjectIndex), Object Angle Y(Player.DynamicObjectIndex), Object Angle Z(Player.DynamicObjectIndex)
X# = Object Position X(Player.ControlObjectIndex)
Y# = Object Position Y(Player.ControlObjectIndex)
Z# = Object Position Z(Player.ControlObjectIndex)
Phy Set Rigid Body Position Player.DynamicObjectIndex, X#, Y# + 1, Z#
Temp = Phy Ray Cast All Shapes(X#, Y#, Z#, 0, -1, 0)
Phy Set Rigid Body Position Player.DynamicObjectIndex, X#, Y#, Z#
DistToGround# = Phy Get Ray Cast Distance()
Text 0,0,Str$(DistToGround#)
If DistToGround# < 10
Player.CanJump = 0
`Player.CurrentJumpSpeed# = Player.JumpSpeed#
endif
`If Player.CanJump = 1
`Player.CurrentJumpSpeed# = Player.CurrentJumpSpeed# - 0.01
`EndIf
`If Player.CurrentJumpSpeed# <= 0
`Player.CurrentJumpSpeed# = 0
`EndIf
EndFunction
Function NextObject()
Inc ObjectCount, 1
EndFunction ObjectCount
Problem Solved:
Here is the code I have with the jumping added:
Rem Project: Character Controller
Rem Created: 3/20/2009 3:14:56 AM
Rem ***** Main Source File *****
Phy Start
Phy Set Auto Fixed Timing
AutoCam Off
Sync On : Sync Rate 60
GoSub Define_CharacterController
` Setup Level
Make Object Box 1000, 1000, 1, 1000
Phy Make Rigid Body Static Box 1000
MakeCharacterController(100, 11, 100, 20, 1000, 2000, 1000, 5000) ` Can I calculate the desent value?
Global ControlKeyPressed
` Add crouching
` Add crouch jumping for an extra boost of height (Make sure timing is right
` Is there a smoother way of jumping..seems like the impulse is causing the problem
` Peeking around a corner left and right. This is easy: Tilt on the x-axis
` Hanging on a ledge?
` Climbing over an obstacle?
Do
UpdateCharacterController()
Phy Update
Sync
Loop
Define_CharacterController:
Type CharacterKeys
Up
Down
Right
Left
Run
Jump
EndType
Global DefaultKeys As CharacterKeys
DefaultKeys.Up = 17
DefaultKeys.Down = 31
DefaultKeys.Right = 32
DefaultKeys.Left = 30
DefaultKeys.Run = 42
DefaultKeys.Jump = 57
Type Character
ControlObjectIndex
DynamicObjectIndex
LookSpeed#
WalkSpeed#
RunSpeed#
Keys As CharacterKeys
CanJump
JumpSpeed#
DesentSpeed#
OldCamAngleX#
OldCamAngleY#
CameraAngleX#
CameraAngleY#
EndType
Global Player As Character
Global ObjectCount : ObjectCount = Object Count()
Phy Make Material 1, "Character"
Phy Set Material Restitution 1, 0.0
Phy Set Material Dynamic Friction 1, 0.1
Phy Set Material Static Friction 1, 0.1
Phy Build Material 1
Return
Function MakeCharacterController(X#, Y#, Z#, Size#, WalkSpeed#, RunSpeed#, JumpSpeed#, DesentSpeed#)
Player.ControlObjectIndex = NextObject()
Make Object Sphere Player.ControlObjectIndex, Size#
Position Object Player.ControlObjectIndex, X#, Y#, Z#
Player.DynamicObjectIndex = NextObject()
Make Object Sphere Player.DynamicObjectIndex, Size#
Position Object Player.DynamicObjectIndex, X#, Y#, Z#
Phy Make Rigid Body Dynamic Sphere Player.DynamicObjectIndex, 1 ` Character Material
`Phy Set Rigid Body Mass Player.DynamicObjectIndex, 10
Player.Keys = DefaultKeys
Player.LookSpeed# = 0.4
Player.JumpSpeed# = JumpSpeed#
Player.WalkSpeed# = WalkSpeed#
Player.RunSpeed# = RunSpeed#
Player.DesentSpeed# = DesentSpeed#
EndFunction
Function SetCharacterPosition(X#, Y#, Z#)
`Position Object Player.ControlObjectIndex, X#, Y#, Z#
Phy Set Rigid Body Position Player.DynamicObjectIndex, X#, Y#, Z#
EndFunction
Function SetCharacterRotation(X#, Y#, Z#)
`Rotate Object Player.ControlObjectIndex, X#, Y#, Z#
Phy Set Rigid Body Rotation Player.DynamicObjectIndex, X#, Y#, Z#
EndFunction
Function SetCharacterLookSpeed(Speed#)
Player.LookSpeed# = Speed#
EndFunction
Function UpdateCharacterController()
Position Camera Object Position X(Player.DynamicObjectIndex), Object Position Y(Player.DynamicObjectIndex), Object Position Z(Player.DynamicObjectIndex)
YRotate Camera WrapValue(Camera Angle Y() + MouseMoveX())
XRotate Camera WrapValue(Camera Angle X() + MouseMoveY())
Move Camera Up 15
If KeyState(Player.Keys.Run) = 1
Speed# = Player.RunSpeed#
Else
Speed# = Player.WalkSpeed#
EndIf
If KeyState(Player.Keys.Left) = 1
Phy Add Rigid Body Local Force Player.DynamicObjectIndex, -Speed#, 0, 0, 5
EndIf
If KeyState(Player.Keys.Right) = 1
Phy Add Rigid Body Local Force Player.DynamicObjectIndex, Speed#, 0, 0, 5
EndIf
If KeyState(Player.Keys.Up) = 1
Phy Add Rigid Body Local Force Player.DynamicObjectIndex, 0, 0, Speed#, 5
EndIf
If KeyState(Player.Keys.Down) = 1
Phy Add Rigid Body Force Player.DynamicObjectIndex, 0, 0, -Speed#, 5
EndIf
If KeyState(Player.Keys.Jump) = 1 and Player.CanJump = 1
Phy Add Rigid Body Force Player.DynamicObjectIndex, 0, Player.JumpSpeed#, 0, 4
Player.CanJump = 0
EndIf
Phy Set Rigid Body Linear Momentum Player.DynamicObjectIndex, 0.0, Phy Get Rigid Body Linear Momentum Y(Player.DynamicObjectIndex), 0.0
Phy Set Rigid Body Angular Velocity Player.DynamicObjectIndex, 0.0, Phy Get Rigid Body Angular Velocity Y(Player.DynamicObjectIndex), 0.0
Phy Set Rigid Body Rotation Player.DynamicObjectIndex, 0.0, Camera Angle Y(), 0.0
Position Object Player.ControlObjectIndex, Object Position X(Player.DynamicObjectIndex), Object Position Y(Player.DynamicObjectIndex), Object Position Z(Player.DynamicObjectIndex)
Rotate Object Player.ControlObjectIndex, Object Angle X(Player.DynamicObjectIndex), Object Angle Y(Player.DynamicObjectIndex), Object Angle Z(Player.DynamicObjectIndex)
X# = Object Position X(Player.ControlObjectIndex)
Y# = Object Position Y(Player.ControlObjectIndex)
Z# = Object Position Z(Player.ControlObjectIndex)
Phy Set Rigid Body Position Player.DynamicObjectIndex, X#, Y# + 1, Z#
Temp = Phy Ray Cast All Shapes(X#, Y#, Z#, 0, -1, 0)
Phy Set Rigid Body Position Player.DynamicObjectIndex, X#, Y#, Z#
DistToGround# = Phy Get Ray Cast Distance()
Text 0,0,Str$(DistToGround#)
If DistToGround# < 10
Player.CanJump = 1
Else
` Simulate Extra Gravity to Character Controller
Phy Add Rigid Body Force Player.DynamicObjectIndex, 0, -Player.DesentSpeed#, 0, 5
Endif
EndFunction
Function NextObject()
Inc ObjectCount, 1
EndFunction ObjectCount
remstart
Function UpdateCharacterController()
Phy Set Rigid Body Linear Damping Player.DynamicObjectIndex, 8
Position Object Player.ControlObjectIndex, Object Position X(Player.DynamicObjectIndex), Object Position Y(Player.DynamicObjectIndex), Object Position Z(Player.DynamicObjectIndex)
` Rotate and position the camera based on the box controller
Player.OldCamAngleY# = Player.CameraAngleY#
Player.OldCamAngleX# = Player.CameraAngleX#
Player.CameraAngleY# = WrapValue(Player.CameraAngleY# + MouseMoveX() * Player.LookSpeed#)
Player.CameraAngleX# = WrapValue(Player.CameraAngleX# + MouseMoveY() * Player.LookSpeed#)
YRotate Object Player.ControlObjectIndex, CurveAngle(Player.CameraAngleY#, Player.OldCamAngleY#, 24)
XRotate Camera CurveAngle(Player.CameraAngleX#, Player.OldCamAngleX#, 24)
If KeyState(Player.Keys.Run) = 1
Speed# = Player.RunSpeed#
Else
Speed# = Player.WalkSpeed#
EndIf
If KeyState(Player.Keys.Up) = 1
Move Object Player.ControlObjectIndex, Speed#
Endif
If KeyState(Player.Keys.Down) = 1
Move Object Player.ControlObjectIndex, -Speed#
EndIf
If KeyState(Player.Keys.Left) = 1
Move Object Left Player.ControlObjectIndex, Speed#
EndIf
If KeyState(Player.Keys.Right) = 1
Move Object Right Player.ControlObjectIndex, Speed#
EndIf
If KeyState(Player.Keys.Jump) = 1 and Player.CanJump = 0
Player.CanJump = 1
Player.CurrentJumpSpeed# = Player.JumpSpeed#
endif
If Player.CanJump = 1
Player.CurrentJumpSpeed# = Player.CurrentJumpSpeed# - 0.01
EndIf
If Player.CurrentJumpSpeed# <= 0
Player.CurrentJumpSpeed# = 0
EndIf
X# = Object Position X(Player.ControlObjectIndex)
Y# = Object Position Y(Player.ControlObjectIndex)
Z# = Object Position Z(Player.ControlObjectIndex)
Phy Set Rigid Body Position Player.DynamicObjectIndex, X#, Y# + 1, Z#
Temp = Phy Ray Cast All Shapes(X#, Y#, Z#, 0, -1, 0)
Phy Set Rigid Body Position Player.DynamicObjectIndex, X#, Y#, Z#
DistToGround# = Phy Get Ray Cast Distance()
Gravity# = 0.07
If DistToGround# > 0.5
Move Object Down Player.ControlObjectIndex, Gravity#
Else
Player.CanJump = 0
EndIf
Move Object Up Player.ControlObjectIndex, Player.CurrentJumpSpeed#
X# = Object Position X(Player.ControlObjectIndex)
Y# = Object Position Y(Player.ControlObjectIndex)
Z# = Object Position Z(Player.ControlObjectIndex)
Position Camera X#, Y#, Z#
Rotate Camera Camera Angle X(), Object Angle Y(Player.ControlObjectIndex), Object Angle Z(Player.ControlObjectIndex)
Phy Set Rigid Body Position Player.DynamicObjectIndex, X#, Y#, Z#
Phy Set Rigid Body Rotation Player.DynamicObjectIndex, Object Angle X(Player.ControlObjectIndex), Object Angle Y(Player.ControlObjectIndex), Object Angle Z(Player.ControlObjectIndex)
EndFunction
` demonstrates how to move an object around a scene
` we begin by starting the physics process and setting some initial
` properties of the application, such as sync rate and camera position
phy start
autocam off
sync on
sync rate 60
color backdrop 0
position camera 0, 20, -100
rem stripe textures
`load image "stripe5.png",8
make object sphere 8,400,48,48
`texture object 8,8
`scale object texture 8,6,6
set object cull 8,0
`load image "stripe6.png",1
` a box is made to represent our floor object
make object box 1, 150, 1, 150
`texture object 1,1
phy make rigid body static box 1
Color Object 1, RGB(RND(255),RND(255),RND(255))
` a cube is created and positioned on top of the floor over to the left
make object cube 2, 10
position object 2, 0, 10, 0
phy make rigid body dynamic box 2
`Phy Set Rigid Body Kinematic 2, 1
Color Object 2, RGB(RND(255),RND(255),RND(255))
`Hide Object 2
`phy set rigid body gravity 2, 0
` the dark physics logo is loaded and displayed with a sprite
`load image "logo.png", 100000
`sprite 1, 0, 600 - 60, 100000
`position camera 0, 180, 0
`rotate camera 90, 0, 0
` Because
` now we get to our main program loop
do
Position Camera Object Position X(2), Object Position Y(2), Object Position Z(2)`+20
`Move Camera -30
YRotate Camera WrapValue(Camera Angle Y() + MouseMoveX())
` Figure out how to rotate the camera so it looks correct
`YRotate Camera Object Angle Y(2)
`PrintC MouseMoveX()
`Phy Set Rigid Body Angular Velocity 2, 0, MMX#, 0
`Text 0, 0, Str$(Object Angle Y(2))
` turn left
if leftkey ( ) = 1
`phy set rigid body angular velocity 2, 0, -1.0, 0
phy add rigid body local force 2, -1000, 0, 0, 5
endif
` turn right
if rightkey ( ) = 1
`phy set rigid body angular velocity 2, 0, 1.0, 0
phy add rigid body local force 2, 1000, 0, 0, 5
endif
` apply force
if upkey ( ) = 1
phy add rigid body local force 2, 0, 0, 1000, 5
endif
if downkey ( ) = 1
phy add rigid body local force 2, 0, 0, -1000, 5
endif
` stop linear momentum
phy set rigid body linear momentum 2, 0.0, 0.0, 0.0
` reset angular velocity
phy set rigid body angular velocity 2, 0.0, Phy Get Rigid Body Angular Velocity Y(2), 0.0
Phy Set Rigid Body Rotation 2, Camera Angle X(), Camera Angle Y(), Camera Angle Z()
` now we update the physics simulation and the screen
phy update
sync
loop
remend
New Questions and ideas:
How can I crouch the object and size the object on the y axis so it will return the correct ray cast response?
Wouldn't you have to size the object then use: Phy Delete Rigid Body then: Phy Make Rigid Body Dynamic Box again?
After figuring out crouching how would I crouch jump?
In halo 2 you would press it right after you jump.
How would I figure out when I would accept the executed crouch jump?
Would I be able to execute the jump when I reach a certain height and will only work if it is under a certain height?
Like this: Crouch Jumping will only work between these heights off the ground: 11 and < 12.
Would this be the correct way of doing this or would timing be used?
Is there a smoother way of jumping? (seems like the impulse of the force is causing the problem) (I don't want to use velocity though. Velocity will cause collision problems.
I also have been trying to figure out how I would hang on a ledge.
I would have to figure out how to calculate if there is a ledge in front of the character.
Then I have to figure out how to grab on it and move down a bit after grabbing on.
After that I would have to figure out how to pull the character up and over the wall.
The last thing I would have to figure out is the character's stamina related to how fast he can run, but that is the easy part.
Thanks,
Dark Fire
My future self met up with one day to teach me what I know today.