kinematic_character_2d.rst 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. .. _doc_kinematic_character_2d:
  2. Kinematic Character (2D)
  3. ========================
  4. Introduction
  5. ~~~~~~~~~~~~
  6. Yes, the name sounds strange. "Kinematic Character". What is that?
  7. The reason is that when physics engines came out, they were called
  8. "Dynamics" engines (because they dealt mainly with collision
  9. responses). Many attempts were made to create a character controller
  10. using the dynamics engines but it wasn't as easy as it seems. Godot
  11. has one of the best implementations of dynamic character controller
  12. you can find (as it can be seen in the 2d/platformer demo), but using
  13. it requieres a considerable level of skill and understanding of
  14. physics engines (or a lot of patience with trial and error).
  15. Some physics engines such as Havok seem to swear by dynamic character
  16. controllers as the best alternative, while others (PhysX) would rather
  17. promote the Kinematic one.
  18. So, what is really the difference?:
  19. - A **dynamic character controller** uses a rigid body with infinite
  20. inertial tensor. Basically, it's a rigid body that can't rotate.
  21. Physics engines always let objects collide, then solve their
  22. collisions all together. This makes dynamic character controllers
  23. able to interact with other physics objects seamlessly (as seen in
  24. the platformer demo), however these interactions are not always
  25. predictable. Collisions also can take more than one frame to be
  26. solved, so a few collisions may seem to displace a tiny bit. Those
  27. problems can be fixed, but require a certain amount of skill.
  28. - A **kinematic character controller** is assumed to always begin in a
  29. non-colliding state, and will always move to a non colliding state.
  30. If it starts in a colliding state, it will try to free itself (like
  31. rigid bodies do) but this is the exception, not the rule. This makes
  32. their control and motion a lot more predictable and easier to
  33. program. However, as a downside, they can't directly interact with
  34. other physics objects (unless done by hand in code).
  35. This short tutorial will focus on the kinematic character controller.
  36. Basically, the oldschool way of handling collisions (which is not
  37. necessarily simpler under the hood, but well hidden and presented as a
  38. nice and simple API).
  39. Physics process
  40. ~~~~~~~~~~~~~~~
  41. To manage the logic of a kinematic body or character, it is always
  42. advised to use physics process, because it's called before physics step and its execution is
  43. in sync with physics server, also it is called the same amount of times
  44. per second, always. This makes physics and motion calculation work in a
  45. more predictable way than using regular process, which might have spikes
  46. or lose precision if the frame rate is too high or too low.
  47. ::
  48. extends KinematicBody2D
  49. func _physics_process(delta):
  50. pass
  51. Scene setup
  52. ~~~~~~~~~~~
  53. To have something to test, here's the scene (from the tilemap tutorial):
  54. :download:`kbscene.zip <files/kbscene.zip>`. We'll be creating a new scene
  55. for the character. Use the robot sprite and create a scene like this:
  56. .. image:: img/kbscene.png
  57. Let's add a circular collision shape to the collision body, create a new
  58. CircleShape2D in the shape property of CollisionShape2D. Set the radius
  59. to 30:
  60. .. image:: img/kbradius.png
  61. **Note: As mentioned before in the physics tutorial, the physics engine
  62. can't handle scale on most types of shapes (only collision polygons,
  63. planes and segments work), so always change the parameters (such as
  64. radius) of the shape instead of scaling it. The same is also true for
  65. the kinematic/rigid/static bodies themselves, as their scale affect the
  66. shape scale.**
  67. Now create a script for the character, the one used as an example
  68. above should work as a base.
  69. Finally, instance that character scene in the tilemap, and make the
  70. map scene the main one, so it runs when pressing play.
  71. .. image:: img/kbinstance.png
  72. Moving the Kinematic character
  73. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  74. Go back to the character scene, and open the script, the magic begins
  75. now! Kinematic body will do nothing by default, but it has a really
  76. useful function called :ref:`KinematicBody2D.move() <class_KinematicBody2D_move>`.
  77. This function takes a :ref:`Vector2 <class_Vector2>` as
  78. an argument, and tries to apply that motion to the kinematic body. If a
  79. collision happens, it stops right at the moment of the collision.
  80. So, let's move our sprite downwards until it hits the floor:
  81. ::
  82. extends KinematicBody2D
  83. func _physics_process(delta):
  84. move( Vector2(0,1) ) #move down 1 pixel per physics frame
  85. The result is that the character will move, but stop right when
  86. hitting the floor. Pretty cool, huh?
  87. The next step will be adding gravity to the mix, this way it behaves a
  88. little more like an actual game character:
  89. ::
  90. extends KinematicBody2D
  91. const GRAVITY = 200.0
  92. var velocity = Vector2()
  93. func _physics_process(delta):
  94. velocity.y += delta * GRAVITY
  95. var motion = velocity * delta
  96. move( motion )
  97. Now the character falls smoothly. Let's make it walk to the sides, left
  98. and right when touching the directional keys. Remember that the values
  99. being used (for speed at least) is pixels/second.
  100. This adds simple walking support by pressing left and right:
  101. ::
  102. extends KinematicBody2D
  103. const GRAVITY = 200.0
  104. const WALK_SPEED = 200
  105. var velocity = Vector2()
  106. func _physics_process(delta):
  107. velocity.y += delta * GRAVITY
  108. if (Input.is_action_pressed("ui_left")):
  109. velocity.x = -WALK_SPEED
  110. elif (Input.is_action_pressed("ui_right")):
  111. velocity.x = WALK_SPEED
  112. else:
  113. velocity.x = 0
  114. var motion = velocity * delta
  115. # The second parameter of move_and_slide is the normal pointing up.
  116. # In the case of a 2d platformer, in Godot upward is negative y, which translates to -1 as a normal.
  117. move_and_slide(motion, Vector2(0, -1))
  118. And give it a try.
  119. This is a good starting point for a platformer. A more complete demo can be found in the demo zip distributed with the
  120. engine, or in the
  121. https://github.com/godotengine/godot-demo-projects/tree/master/2d/kinematic_character.