I have 2D topdown shooter game where there are zombies - and the player shoots them.

When I used "move_to" in the bullet script to check if it collided with a zombie when I shot them, it seemed that the bullet stopped in front of the zombie's face and it meant the collision system worked.

Then I changed "moveto" to "setpos" by adding bullet's position little by little in an idle process to simulate real bullets's movements, and added a code that would print something if the bullet was colliding with a zombie.

But it seemed that "set_pos" made the collision system fails. I didn't get any printed text in the output.

Is there any ways to fix this? I also think to change the zombie and bullet to rigidbodies and use "setlinearvelocity" or others such as apply force, impulse, etc, instead of "set_pos", but I really don't understand how to use those codes to make the bullet shoots to the mouse pointer with static velocity.

Here's my bullet's code:

``````extends KinematicBody2D

var damage
var xmove
var ymove
=get_tree().get_root().get_child(0).get_node("player").get_node("hand")

const SCREEN_WIDTH = 960
const SCREEN_HEIGHT = 640

signal hit(damage)

set_pos(Vector2(hand.get_global_pos().x,hand.get_global_pos().y))

func shoot(attack,posx,posy):
damage = attack
look_at(Vector2(posx,posy))
xmove = (get_pos().x - posx) * -1 / 100
ymove = (get_pos().y - posy) * -1 / 100
if abs(xmove) && abs(ymove) < 1.5:
xmove *= 3
ymove *= 3
if abs(xmove) && abs(ymove) > 4:
xmove /= xmove / 4
ymove /= ymove / 4
print (xmove,ymove)
show()
set_process(true)

func _process(delta):
if is_colliding():
print("HI")
emit_signal("hit",damage)
queue_free()
set_pos(Vector2(get_pos().x+xmove,get_pos().y+ymove))
if get_pos().x < (0-SCREEN_WIDTH)/2:
queue_free()
elif get_pos().x > SCREEN_WIDTH/2:
queue_free()
if get_pos().y < (0-SCREEN_HEIGHT)/2:
queue_free()
elif get_pos().y > SCREEN_HEIGHT/2:
queue_free()
``````

Thank you really much for helping, and sorry for my bad English.

in Engine

+1 vote

You shouldn't use `set_pos()` with physics bodies. When you do, you circumvent the physics and collision detection. The proper way to move a `KinematicBody2D` is with `move()` or `move_to()`. If you want a steady velocity, just move the same amount every frame. See below:

Also, you can greatly simplify your code by using a `VisibilityNotifier2D` node and calling `queue_free()` on its `exit_screen` signal instead of that chain of `if` statements.

Finally, you're using way too many unnecessary x/y variables when things like `get_pos()`already return `Vector2` objects which you're changing them to anyway. Look how much simpler you can make this:

``````extends KinematicBody2D

var damage
var velocity  = Vector2(500, 0) # use this instead of xmove/ymove

# this should be queried in _ready() from the project settings
const SCREEN_WIDTH = 960
const SCREEN_HEIGHT = 640

signal hit(damage)

set_pos(hand.get_global_pos())

func shoot(attack, pos):
damage = attack
look_at(pos)
velocity = velocity.rotated(get_pos.angle_to(pos))

# I'm not clear what you're trying to do in this part
# but none of it is necessary with a constant speed
#if abs(xmove) && abs(ymove) < 1.5:  # what is this for?
#xmove *= 3
#ymove *= 3
#if abs(xmove) && abs(ymove) > 4:  # again, I don't think this if is doing what you want
#    xmove /= xmove / 4  # you are dividing twice here
#    ymove /= ymove / 4  # this is equivalent to
#                          xmove = xmove / (xmove / 4)
#                          which is xmove = xmove * 4
show()
set_process(true)

func _process(delta):
if is_colliding():
print("HI")
emit_signal("hit",damage)
queue_free()
move(velocity * delta)  # you should use delta here

func _on_VisibilityNotifier2D_exit_screen():
queue_free()
``````

I recommend you look at some of the sample projects and docs about how to use Godot, as I think you are missing some of the fundamental concepts. http://docs.godotengine.org/en/stable/learning/features/physics/physics_introduction.html is a good place to start.

by (21,920 points)
selected by

Thank you for giving the simpler version! I am really confused out seeing the version of mine :D I'm sorry for my inefficient way to code things, maybe not only the doc you linked to me that I need to read, but also docs how to code things efficiently, since I'm not even a programmer.

I really didn't find out to use `move()` or `move_to()` instead of `set_pos()`, how foolish I am. Sorry for my carelessness :v

## but none of it is necessary with a constant speed

I'm doing it not for a constant speed, but it is because the mouse pointer's pos is sometimes further and sometimes nearer from the player. The further the mouse pointer's pos is, the bigger xmove, ymove and bullet's velocity will (in my version of code). That's why I checked first if a bullet is too slow or too fast, caused by how far the mouse pointer is from the player.

Frankly speaking I also want to ask how to fix the velocity, but when I posted that some days ago, it seemed the forum was bugged and my question didn't appear. Before asking the same question again, I was faced by another problem, which is the problem I was talking about in this page.

In the case of kinematic bodies you can use `set_pos` but only if you want them to act as moving static bodies, ignoring overlaps and pushing everything that is "aware" of overlaps/collisions (like on the rest of the common engines).