#Problem with bullets

51 messages · Page 1 of 1 (latest)

oak blade
#

Hello, after 2h of research I have come to the conclusion that to make my top down character shoot I would need something like this:

var bullet_instance = bullet.instance()
bullet_instance.position = get_global_position()
bullet_instance.rotation_degrees = rotation_degrees
bullet_instance.apply_impulse(Vector2D(), Vector2D(bullet_speed, 0).rotated(rotation)
get_tree().get_root().add_child(bullet_instance)

In the youtube videos and forums I've seen how this alone makes the bullet shoot. However it is not my case because I get this: (first pic)
The bullet is just teleporting there, and stays there. Is there anything I've missed? I will attach the implementation, if it helps(half of it is the "My first 2D game") (ignore the placeholder sprites)

#

#include "Weapon.hpp"
#include "Mob.hpp"
#include <SceneTree.hpp>

using namespace godot;


void Weapon::_register_methods()
{
  godot::register_method("_ready", &Weapon::_ready);
  godot::register_method("shoot", &Weapon::shoot);
  godot::register_method("stopShoot", &Weapon::stopShoot);
  godot::register_property("Damage", &Weapon::damage, 10.0f);
  godot::register_property("BulletSpeed", &Weapon::bulletSpeed, 300.0f);
  godot::register_property("bullet_scene", &Weapon::bullet_scene, (godot::Ref<godot::PackedScene>)nullptr);

}

void Weapon::_ready()
{
  weaponLook = get_node<AnimatedSprite>("WeaponLook");
}

void Weapon::shoot()
{
  weaponLook->set_animation("gunShoot"); 
  godot::RigidBody2D *bullet =static_cast<RigidBody2D*>(bullet_scene->instance());

  bullet->set_global_position(get_global_position());
  bullet->set_rotation(get_rotation());
  bullet->apply_impulse(Vector2(), Vector2(bulletSpeed, 0.0f).rotated(get_global_rotation()));
  call_deferred("add_child", bullet);

}

void Weapon::stopShoot()
{
  weaponLook->set_animation("idle");
}

AND PLAYER

void Player::_process(const double p_delta)
{
    //movement code

    bool pressed = _input->get_action_strength("shoot_primary");  

    weapon->look_at(mousePositon);
    if(pressed)
        weapon->shoot();
    else
       weapon->stopShoot();
      ...
    //movement code
}
obtuse violet
#

I believe you need to multiply bulletSpeed * delta.
Ideally inside physics_process.

#

You need to restructure your code a little bit I'm afraid.

#

Probably you can move the "apply_impulse" logic to the physics_process method of your bullet (instead of having it in your weapon).

oak blade
#

but woudn't that break encapsulation?

obtuse violet
#

I understand your concern but think it this way:

  • you shoot the bullet
  • the bullet "gets into existence "
  • now it makes sense that bullet motion is coded inside the bullet scene, not the weapon.
  • in fact the bullet is no longer tied to the weapon in any way. It's not even a child of the weapon
#

I believe in this specific case the encapsulation is improved if the weapon can only "create/shoot" a bullet from a specific position with a specific speed. All the rest is competence of the bullet.

oak blade
#

Hmm, yes that makes sense

#

I was trying to do a little abstraction here, but I will see if that is going to work

oak blade
#

but now it ignores all the code in _proccess(delta)

#

Any idea why that might be?

#

fixed that

#

But now it doesnt work again bruhh

#

Okay so now my code looks like this

#
void godot::Player::_physics_process(const double delta)
{
    if(_input->get_action_strength("shoot_primary"))
    {
        godot::RigidBody2D *bullet =static_cast<RigidBody2D*>(bullet_scene->instance());

        bullet->set_global_position(weapon->get_global_position());
        bullet->set_rotation(weapon->get_rotation());
        bullet->apply_impulse(Vector2(), Vector2(1000, 0.0f).rotated(get_global_rotation()));
        call_deferred("add_child", bullet);
    }
}
#

and

#
void Player::_process(const double p_delta)
{
    godot::Vector2 velocity(0,0);
    godot::Vector2 mousePositon = get_global_mouse_position();
    velocity.x = _input->get_action_strength("move_right") - _input->get_action_strength("move_left");
    velocity.y = _input->get_action_strength("move_down") - _input->get_action_strength("move_up");

    bool pressed = _input->get_action_strength("shoot_primary");  

    weapon->look_at(mousePositon);
    if(pressed)
        weapon->shoot();
    else
       weapon->stopShoot();
#

Now it does the same thing as before

#

However there is a weird thing going on

#

doing this:

#

Notice the difference

#

This will make the bullet go as intended but will the normal process will not work (of course)

#

However doing this:

#
void Player::_process(const double p_delta)
{
    godot::Vector2 velocity(0,0);
    godot::Vector2 mousePositon = get_global_mouse_position();
    velocity.x = _input->get_action_strength("move_right") - _input->get_action_strength("move_left");
    velocity.y = _input->get_action_strength("move_down") - _input->get_action_strength("move_up");

    bool pressed = _input->get_action_strength("shoot_primary");  

    weapon->look_at(mousePositon);
    if(pressed)
      {
        godot::RigidBody2D *bullet =static_cast<RigidBody2D*>(bullet_scene->instance());

        bullet->set_global_position(weapon->get_global_position());
        bullet->set_rotation(weapon->get_rotation());
        bullet->apply_impulse(Vector2(), Vector2(1000, 0.0f).rotated(get_global_rotation()));
        call_deferred("add_child", bullet);
      
        weapon->shoot();
    }
    else
       weapon->stopShoot();
#

will not work either

#

however the other way around works

#

so gg I guess

#

If you would have any tips on how I could make this abstraction, that means I want to have different weapons and different bullets for each, I would appreciate it

obtuse violet
#

No idea on the specific problem you are seeing. Is that Godot with C#.
I haven't used C# so I don't know the specifics of the language, like the "register method thing"

obtuse violet
#

I see that you are creating a local variable called velocity. But you are not doing a renting with it.

#

Apparently

oak blade
oak blade
obtuse violet
#

physics_process is the right place to apply_forces.

oak blade
oak blade
obtuse violet
#

Hey. I might be wrong, see this.

#

An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason it should only be used when simulating one-time impacts (use the "_force" functions otherwise).

From official docs

#

That means that I don't really know what was happening in your initial code.

oak blade
#

so it wasnt supposed to be in the physics processor?

obtuse violet
#

Sorry for my previous misleading answer.

#

Not identical requirement but it uses apply_central_impulse

oak blade
#

Hmm interesting

#

Thank you I will check it out