Bullet Collision problems with KinematicBody2D

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By JJHaggar

Hello,

I am new to Godot, and I am trying to make a 2d top-down shooter (a simple Asteroids clone) to learn a bit about Godot basics, but I encountered a ‘strange’ behaviour when I added bullets, you can watch it here: https://youtu.be/2Ywcl4VGeNY?t=4s (they are slow bullets but the problem is not that, the problem it’s that they collide & push the ship and the other bullets, and I’d like to overwrite that behaviour somehow)

The project is here in case you want to take a look (this is the folder of the Asteroids clone, the rest of the project is a bit messy, sorry) Bitbucket

The ship is a KinematicBody2D, and the bullets are also KinematicBody2D, and I don’t know if it’s normal that when they collide they automatically push each other as you can see on the video.

https://i.imgur.com/74m13zc.gif

Can I control what happens when 2 KinematicBody2D meet each other? (for example go through each other? bounce?) Or maye I should be using area2D instead? (is what I can extract more or less after reading the docs Physics introduction — Godot Engine (latest) documentation in English but I’m not sure at all)

SpaceShip code:

extends KinematicBody2D

const ACCELERATION = 2
const ROTATION_ACCELERATION = 5
const MAX_SPEED = 100
var motion = Vector2()
var rotation_deg = 0
const SCREEN_WIDTH = 480
const SCREEN_HEIGHT = 270
	
func _input(event):
	if event.is_action_pressed("fire"):
		$BulletSpawn.fire(rotation_deg)
		return
		
func _process(delta):
	$"../DebugLabel".text = "angle=" + str(rotation_deg) + "\n" + \
							"sin=" + str(sin(deg2rad(rotation_deg))) + "\n" + \
							"cos=" + str(cos(deg2rad(rotation_deg))) + "\n" + \
							"motion=" + str(motion) + "\n" + \
							"pos=" + str(position) + "\n" + \
							"sin=" + str(sin(deg2rad(rotation_deg)))

func _physics_process(delta):
	if Input.is_action_pressed("ui_left"):
		rotation_deg -= ROTATION_ACCELERATION
	if Input.is_action_pressed("ui_right"):
		rotation_deg += ROTATION_ACCELERATION
	rotation = deg2rad(rotation_deg)
	
	if Input.is_action_pressed("ui_up"):
		motion.x += ACCELERATION * cos(deg2rad(rotation_deg))
		motion.y += ACCELERATION * sin(deg2rad(rotation_deg))
	if Input.is_action_pressed("ui_down"):
		motion.x -= ACCELERATION * cos(deg2rad(rotation_deg))
		motion.y -= ACCELERATION * sin(deg2rad(rotation_deg))
	move_and_slide(motion)
	
	if position.x > SCREEN_WIDTH:
		position.x = 0
	if position.y > SCREEN_HEIGHT:
		position.y = 0
	if position.x < 0:
		position.x = SCREEN_WIDTH
	if position.y < 0:
		position.y = SCREEN_HEIGHT
		
	if motion.x > MAX_SPEED:
		motion.x = MAX_SPEED
	if motion.y > MAX_SPEED:
		motion.y = MAX_SPEED
	if motion.x < -MAX_SPEED:
		motion.x = -MAX_SPEED
	if motion.y < -MAX_SPEED:
		motion.y = -MAX_SPEED
		
	if rotation_deg > 360:
		rotation_deg = -360
	if rotation_deg < -360:
		rotation_deg = 360

Bullet code:

extends KinematicBody2D
var angle = 0.0
const SPEED = 50
var motion = Vector2()

func _ready():
	set_as_toplevel(true)
	pass
func _physics_process(delta):
	motion.x = SPEED * cos(deg2rad(angle))
	motion.y = SPEED * sin(deg2rad(angle))
	move_and_slide(motion)

BulletSpawn code:

extends Node2D

var bullet = preload("Bullet.tscn")

func fire(angle):
	var new_bullet = bullet.instance()
	new_bullet.angle = angle
	new_bullet.position = get_parent().position
	get_parent().get_parent().add_child(new_bullet)

I’ve been searching info and trying to figure out which approach would be best but I fear I’ve still got poor programming skills so I feel a bit overwhelmed.
Info/Things I tried:
Godot 3.0: Using KinematicBody2D · KCC Blog I Downloaded the example to test but I cannot get the same results by myself :S
https://forum.godotengine.org/3247/i-need-help-about-collision-and-area2d Outdated (it’s for godot 2)
Reddit - Dive into anything
https://forum.godotengine.org/12942/best-node-for-a-bullet?

I hope somebody can point me in the correct direction. Thank you for your help! :slight_smile:

:bust_in_silhouette: Reply From: metin

I think all you have to do is put the ship and the bullet in different collision layers. You can do that in the editor, no coding needed. Maybe this will help you:
http://kidscancode.org/blog/2018/02/godot3_kinematic2d/

That worked pretty well! Thank you very much! :smiley:

Though, there is still an unsolved problem if I use this technique: The bullets cannot go through enemies after hitting them, and the same happens with the SpaceShip. I recorded another video: https://youtu.be/ayFtB8mKvmI?t=2s

I configured the different collision layers for the elements this way:

  • SpaceShip: layer=player mask=coins
  • Bullets: layer=bullets mask=enemies
  • Enemy: layer=enemies mask=player

Is there any way of control the behaviour of the KinematicBodies2D when they collide by making them go one through another? I would like the bullets to be able to damage and go through some enemies, and also to rebound or dissappear when hitting other enemies.

Thank you again! :slight_smile:

JJHaggar | 2018-06-23 04:43

I think it would be better to not use KinematicBody2D for the bullet. You should use a ray cast that has the length of your bullet and travels into the direction it got shot to.
Look here:
Ray-casting — Godot Engine (3.0) documentation in English
and
RayCast2D — Godot Engine (3.0) documentation in English

metin | 2018-06-23 13:23

I wasn’t able to implement the ray cast solution, but in the meantime I found another video that helped me https://www.youtube.com/watch?v=RZyiy9bbeNE

So the solution that worked best for me was to make the bullets nodes of type “area2D”, now my bullet can detect any bodies that it goes through :slight_smile:

Anyway, the ray-casting seems really interesting, I think I’ll try to use it with other bullet types, lasers and such, thanks! :smiley:

JJHaggar | 2018-06-24 11:04