Browse Source

Merge pull request #1314 from paulloz/csharp-tutorials-physics

 Translate Tutorials/Physics to C#
Chris Bradfield 7 years ago
parent
commit
a5ca668009

+ 98 - 8
tutorials/physics/physics_introduction.rst

@@ -215,8 +215,9 @@ the physics engine.
 
 For example, here is the code for an "Asteroids" style spaceship:
 
-::
-    
+.. tabs::
+ .. code-tab:: gdscript GDScript
+
     extends RigidBody2D
 
     var thrust = Vector2(0, 250)
@@ -234,6 +235,29 @@ For example, here is the code for an "Asteroids" style spaceship:
             rotation_dir -= 1
         set_applied_torque(rotation_dir * torque)
 
+ .. code-tab:: csharp
+
+    class Spaceship : RigidBody2D
+    {
+        private Vector2 thrust = new Vector2(0, 250);
+        private float torque = 20000;
+
+        public override void _IntegrateForces(Physics2DDirectBodyState state)
+        {
+            if (Input.IsActionPressed("ui_up"))
+                SetAppliedForce(thrust.Rotated(Rotation));
+            else
+                SetAppliedForce(new Vector2());
+
+            var rotationDir = 0;
+            if (Input.IsActionPressed("ui_right"))
+                rotationDir += 1;
+            if (Input.IsActionPressed("ui_left"))
+                rotationDir -= 1;
+            SetAppliedTorque(rotationDir * torque);
+        }
+    }
+
 Note that we are not setting the ``linear_velocity`` or ``angular_velocity``
 properties directly, but rather applying forces (``thrust`` and ``torque``) to
 the body and letting the physics engine calculate the resulting movement.
@@ -290,7 +314,8 @@ information to determine the response.
 For example, if you want to find the point in space where the collision
 occurred:
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
     extends KinematicBody2D
     
@@ -301,18 +326,49 @@ occurred:
         if collision_info:
             var collision_point = collision_info.position
 
+ .. code-tab:: csharp
+
+    class Body : KinematicBody2D
+    {
+        private Vector2 velocity = new Vector2(250, 250);
+
+        public override void _PhysicsProcess(float delta)
+        {
+            var collisionInfo = MoveAndCollide(velocity * delta);
+            if (collisionInfo != null)
+            {
+                var collisionPoint = collisionInfo.GetPosition();
+            }
+        }
+    }
+
 Or to bounce off of the colliding object:
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
     extends KinematicBody2D
     
     var velocity = Vector2(250, 250)
     
     func _physics_process(delta):
-        var collide = move_and_collide(velocity * delta)
-        if collide:
-            velocity = velocity.bounce(collide.normal)
+        var collision_info = move_and_collide(velocity * delta)
+        if collision_info:
+            velocity = velocity.bounce(collision_info.normal)
+
+ .. code-tab:: csharp
+
+    class Body : KinematicBody2D
+    {
+        private Vector2 velocity = new Vector2(250, 250);
+
+        public override void _PhysicsProcess(float delta)
+        {
+            var collisionInfo = MoveAndCollide(velocity * delta);
+            if (collisionInfo != null)
+                velocity = velocity.Bounce(collisionInfo.Normal);
+        }
+    }
 
 :ref:`move_and_slide <class_KinematicBody2D_move_and_slide>`
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -330,7 +386,8 @@ without writing very much code.
 For example, use the following code to make a character that can walk along
 the ground (including slopes) and jump when standing on the ground:
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
     extends KinematicBody2D
 
@@ -358,5 +415,38 @@ the ground (including slopes) and jump when standing on the ground:
     	get_input()
     	velocity = move_and_slide(velocity, Vector2(0, -1))
 
+ .. code-tab:: csharp
+
+    class Body : KinematicBody2D
+    {
+        private float runSpeed = 350;
+        private float jumpSpeed = -1000;
+        private float gravity = 2500;
+
+        private Vector2 velocity = new Vector2();
+
+        private void getInput()
+        {
+            velocity.x = 0;
+
+            var right = Input.IsActionPressed("ui_right");
+            var left = Input.IsActionPressed("ui_left");
+            var jump = Input.IsActionPressed("ui_select");
+
+            if (IsOnFloor() && jump)
+                velocity.y = jumpSpeed;
+            if (right)
+                velocity.x += runSpeed;
+            if (left)
+                velocity.x -= runSpeed;
+        }
+
+        public override void _PhysicsProcess(float delta)
+        {
+            velocity.y += gravity * delta;
+        }
+    }
+
+
 See :ref:`doc_kinematic_character_2d` for more details on using ``move_and_slide()``,
 including a demo project with detailed code.

+ 92 - 10
tutorials/physics/ray-casting.rst

@@ -51,26 +51,51 @@ must be used.
 
 Use the following code in 2D:
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDscript
 
     func _physics_process(delta):
         var space_rid = get_world_2d().space
         var space_state = Physics2DServer.space_get_direct_state(space_rid)
 
+ .. code-tab:: csharp
+
+    public override void _PhysicsProcess(float delta)
+    {
+        var spaceRid = GetWorld2d().Space;
+        var spaceState = Physics2DServer.SpaceGetDirectState(spaceRid);
+    }
+
 Or more directly:
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
     func _physics_process(delta):
         var space_state = get_world_2d().direct_space_state
 
+ .. code-tab:: csharp
+
+    public override void _PhysicsProcess(float delta)
+    {
+        var spaceState = GetWorld2d().DirectSpaceState;
+    }
+
 And in 3D:
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
     func _physics_process(delta):
         var space_state = get_world().direct_space_state
 
+ .. code-tab:: csharp
+
+    public override void _PhysicsProcess(float delta)
+    {
+        var spaceState = GetWorld().DirectSpaceState;
+    }
+
 Raycast query
 -------------
 
@@ -78,21 +103,37 @@ For performing a 2D raycast query, the method
 :ref:`Physics2DDirectSpaceState.intersect_ray() <class_Physics2DDirectSpaceState_intersect_ray>`
 may be used. For example:
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
     func _physics_process(delta):
-        var space_state = get_world().direct_space_state
+        var space_state = get_world_2d().direct_space_state
         # use global coordinates, not local to node
         var result = space_state.intersect_ray(Vector2(0, 0), Vector2(50, 100))
 
+ .. code-tab:: csharp
+
+    public override void _PhysicsProcess(float delta)
+    {
+        var spaceState = GetWorld2d().DirectSpaceState;
+        // use global coordinates, not local to node
+        var result = spaceState.IntersectRay(new Vector2(), new Vector2(50, 100));
+    }
+
 The result is a dictionary. If the ray didn't hit anything, the dictionary will
 be empty. If it did hit something it will contain collision information:
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
         if result:
             print("Hit at point: ", result.position)
 
+ .. code-tab:: csharp
+
+        if (result.Count > 0)
+            GD.Print("Hit at point: ", result["position"]);
+
 The ``result`` dictionary when a collision occurs contains the following
 data:
 
@@ -125,14 +166,26 @@ optional third parameter which is an array of exceptions. This is an
 example of how to use it from a KinematicBody2D or any other
 collision object node:
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
     extends KinematicBody2D
 
     func _physics_process(delta):
-        var space_state = get_world().direct_space_state
+        var space_state = get_world_2d().direct_space_state
         var result = space_state.intersect_ray(global_position, enemy_position, [self])
 
+ .. code-tab:: csharp
+
+    class Body : KinematicBody2D
+    {
+        public override void _PhysicsProcess(float delta)
+        {
+            var spaceState = GetWorld2d().DirectSpaceState;
+            var result = spaceState.IntersectRay(globalPosition, enemyPosition, new object[] { this });
+        }
+    }
+
 The exceptions array can contain objects or RIDs.
 
 Collision Mask
@@ -146,7 +199,8 @@ The optional fourth argument for ``intersect_ray()`` is a collision mask. For
 example, to use same mask as the parent body, use the ``collision_mask``
 member variable:
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
     extends KinematicBody2D
 
@@ -155,6 +209,18 @@ member variable:
         var result = space_state.intersect_ray(global_position, enemy_position,
                                 [self], collision_mask)
 
+ .. code-tab:: csharp
+
+    class Body : KinematicBody2D
+    {
+        public override void _PhysicsProcess(float delta)
+        {
+            var spaceState = GetWorld2d().DirectSpaceState;
+            var result = spaceState.IntersectRay(globalPosition, enemyPosition,
+                            new object[] { this }, CollisionMask);
+        }
+    }
+
 
 3D ray casting from screen
 --------------------------
@@ -175,7 +241,8 @@ obtained. This is because ``origin`` changes in orthogonal mode, while
 
 To obtain it using a camera, the following code can be used:
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
     const ray_length = 1000
 
@@ -185,5 +252,20 @@ To obtain it using a camera, the following code can be used:
               var from = camera.project_ray_origin(event.position)
               var to = from + camera.project_ray_normal(event.position) * ray_length
 
+ .. code-tab:: csharp
+
+    private const float rayLength = 1000;
+
+    public override void _Input(InputEvent @event)
+    {
+        if (@event is InputEventMouseButton eventMouseButton && eventMouseButton.Pressed && eventMouseButton.ButtonIndex == 1)
+        {
+            var camera = (Camera)GetNode("Camera");
+            var from = camera.ProjectRayOrigin(eventMouseButton.Position);
+            var to = from + camera.ProjectRayNormal(eventMouseButton.Position) * rayLength;
+        }
+    }
+
+
 Remember that during ``_input()``, the space may be locked, so in practice
 this query should be run in ``_physics_process()``.

+ 21 - 0
tutorials/physics/rigid_body.rst

@@ -46,6 +46,27 @@ Here is a custom ``look_at()`` function that will work reliably with rigid bodie
 	var target_position = $"my_target_spatial_node".get_global_transform().origin
 	look_follow(state, get_global_transform(), target_position)
 
+ .. code-tab:: csharp
+
+    class Body : RigidBody
+    {
+        private void lookFollow(PhysicsDirectBodyState state, Transform currentTransform, Vector3 targetPosition)
+        {
+            var upDir = new Vector3(0, 1, 0);
+            var curDir = currentTransform.basis.Xform(new Vector3(0, 0, 1));
+            var targetDir = (targetPosition - currentTransform.origin).Normalized();
+            var rotationAngle = Mathf.Acos(curDir.x) - Mathf.Acos(targetDir.x);
+
+            state.SetAngularVelocity(upDir * (rotationAngle / state.GetStep()));
+        }
+
+        public override void _IntegrateForces(PhysicsDirectBodyState state)
+        {
+            var targetPosition = (GetNode("my_target_spatial_node") as Spatial).GetGlobalTransform().origin;
+            lookFollow(state, GetGlobalTransform(), targetPosition);
+        }
+    }
+
 
 This function uses the rigid body's ``set_angular_velocity()`` method to rotate the body. It first calculates the difference between the current and desired angle and then adds the velocity needed to rotate by that amount in one frame's time.