0 votes

I am making a Air Hockey game with Godot and I have some issues with the physics. The answer is probably in the docs or here but I can't find it. Take into account I am very new to Godot.

Here is my architecture:

-Game
|-KinematicBody2D # the paddle
| \-CollisionShape2D
|-StaticBodies2d # the walls
| \-CollisionShape2D
\-RigidBody2D
\-CollisionShape2D # the ball

(I omit all the sprite stuff, etc)

When I used set_pos() to move the paddle, when I hit the ball, the ball reacted to the collision and moved as expected. Also the paddle went throught the walls (expected behavior regarding to the function I used).

When I used move(), the paddle collided with the walls and did not go through it as I wanted but it also collided with the ball which did not move.

Is it possible to block a kinematicbody with staticbodies but not with rigidbodies in order to keep the physics stuff ?

I tried this in fixedprocess :

motion = move(motion)
if get_collider() extends RigidBody2D:
    set_pos(get_pos() + motion)

But the ball acted weirdly doing so (moving slowly, strange physics bounce, etc)

in Engine by (12 points)

3 Answers

0 votes

Maybe this tutorial has what you need.

I think it has the same elements you are needing for an air hockey game.

https://www.youtube.com/watch?v=ntYjl_obUDo

by (23 points)
+1 vote

I would't use set_pos() because it works as a teleport. Thus it can produce some unexpected or unwanted behaviour.
Moving kinematicBody with move(...) will always stop if kinematicBody collides with other physics body. If you want to continue with movement (assume that the vector of original movement is denoted by motion), you need:

  1. move the paddle and save the remaining motion with motion = move(motion)
  2. apply impulse to the ball with apply_impulse(...) or with set_linear_velocity(...). You need to calculate the direction and strenght manually, e.g. using collission normals, motion of paddle, motion of rigidbody
  3. continue your movement (maybe in the frame that follows?) with another motion = move(motion). You can test whether whole motion was used by checking size of the motion vector. If not, you can maybe want to return to point 2.
by (675 points)
0 votes

You can safely move a KinematicBody with set_pos, but then it will move as a static body and will go over other bodies.
move prevents overlaps, which means it can't hit anything (even if it says is_colliding), what you can do is a mix of both:


Make a KinematicBody2D main body moved by move in one layer and a child Kinematic body with the same shape on another layer.

KinematicBody2D #the paddle moved by move
|-Sprite
|-Shape
|-KinematicBody2D #The secondary body moved by the paddle
    |-Shape

What this will do is make the main body prevent overlaps with move in a layer while the other body is moved with a "set_pos" behavior by the parent.

The walls will be on one layer/mask pair to work with the main kinematic, the ball on another, the ball should only detect the secondary kinematic to hit it.

That is a simple way to "allow" a KinematicBody2D moved by move to interact with a rigids.

by (7,894 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.