Efficiently spawn and move high amounts of objects like bullets for bullet hells, particles and more.

Overview

Godot Native Bullets

Efficiently spawn and move high amounts of objects like bullets for bullet hells, particles and more.

This is a GDNative plugin, compatible with Godot 3.4.x and up.
Not compatible with Godot 4.x.

Pre-built binaries are provided for:

  • Windows x86-64
  • Linux x86-64
  • macOS Universal (x86-64 + arm64)

Features

  1. Spawn and move high amounts of bullets.
  2. Configure multiple types of bullets, each with its own behaviour.
  3. Set custom properties to categories of bullets or to any single bullet.
  4. Customize bullets using shaders.
  5. Configure bullets with a collision shape, layer and mask of your choice.
  6. Toggle collision detection on or off for each type of bullet.
  7. Set the pool size and z index for every bullet type.
  8. Extend the plugin using C++.

Step by step

Installation

  1. Copy the addons/native_bullets folder in your addons folder.
  2. Navigate to Project -> Project Settings -> Plugin and enable the Native Bullets plugin.

For best performance, toggle use_bvh off in Project Settings -> Physics -> 2d.

BulletKit creation

The first thing to do is create a BulletKit resource and choose how bullets will appear and behave tweaking its properties.

  1. Create a new empty resource and assign one of the scripts you can find in the addons/native_bullets/kits folder to it. In this example, we'll assign the basic_bullet_kit.gdns script. New properties will appear in the resource inspector.

  2. To get started fill the texture property with any texture you have.

  3. As the material, you can use a new material resource using the animated_shader.gdshader you can find in the utils folder. This shader takes care of animating your bullets if you specify more than 1 frame in its parameters.

  4. For now, turn off collisions_enabled, turn use_viewport_as_active_rect on, turn rotate off and set unique_modulate_component to None. See the Reference section to learn more.

This BulletKit resource is now ready to be used!

Bullets node

In order to spawn bullets in the scene, a Bullets node is needed. You can add it as an autoload or as a normal node in the scene.

The Bullets node has to be configured to choose which kinds of bullets will be able to spawn, their maximum amount and their z indices.

  1. Create a new Bullets node.

  2. Choose how many types of bullets this node will be able to spawn. Increase bullet_types_amount to 1 for now.

  3. A new section of the inspector will appear below. Unfold the 0 entry inside the Bullet Types section. Here, drag & drop the BulletKit resource you created earlier to let the node know that you'll want to spawn the bullet described in it!

  4. Choose the maximum amount of bullets setting the pool_size property and the their z_index. 3000 and 1 will be ok.

Nice! Now you can set this node as an autoload for easier access.

Spawn bullets

Now the last step is to spawn a lot of those bullets. Let's create a script.

export(Resource) var bullet_kit


func _process(delta):
	if Input.is_key_pressed(KEY_SPACE):
		shoot()
	if Input.is_key_pressed(KEY_RIGHT):
		rotation += PI * delta
	if Input.is_key_pressed(KEY_LEFT):
		rotation -= PI * delta


func shoot():
	var bullet_velocity = Vector2(cos(global_rotation), sin(global_rotation)) * 30.0

	# Define which properties will be set to the newly spawned bullet.
	# The bullet will be spawned in the same position as this node,
	# travelling in the direction defined by its rotation.
	var properties = {
		"transform": Transform2D(global_rotation, global_position),
		"velocity": bullet_velocity
	}
	# Spawn a bullet using the selected BulletKit and setting the properties defined above.
	# Bullets is an autoload.
	Bullets.spawn_bullet(bullet_kit, properties)

Here you go! Now attach this script to one of your 2D nodes, start the game, press space to shoot and right/left to change the bullets direction!

More examples

Bullets spawning

Spawn bullets using a Bullets node.
In this example Bullets is an autoload.

export(float) var bullets_speed = 50.0


func shoot():
	var bullet_kit = preload("res://path/to/following_bullet_kit.tres")

	# The bullet will be spawned in the same position as this node,
	# travelling in the direction defined by its rotation.
	var bullet_velocity = Vector2(cos(global_rotation), sin(global_rotation)) * bullets_speed
	# Follow the first node inside the Player group.
	var target_node = get_tree().get_nodes_in_group("Player")[0]

	# Define which properties will be set to the newly spawned bullet.
	var properties = {
		"target_node": target_node,
		"transform": Transform2D(global_rotation, global_position),
		"velocity": bullet_velocity
	}
	# Spawn a bullet using the selected BulletKit and setting the properties defined above.
	Bullets.spawn_bullet(bullet_kit, properties)

Bullets handling

You can manipulate and set properties of bullets even after you spawned them.
In this example Bullets is an autoload.

export(float) var bullets_speed = 50.0


func shoot():
	var bullet_kit = preload("res://path/to/basic_bullet_kit.tres")

	# Use `obtain_bullet` to receive an opaque BulletID object.
	var bullet_id = Bullets.obtain_bullet(bullet_kit)

	# You can then use `bullet_id' to set and get properties.
	Bullets.set_bullet_property(bullet_id, "transform", Transform2D(global_rotation, global_position))
	Bullets.set_bullet_property(bullet_id, "velocity", Vector2(cos(global_rotation), sin(global_rotation)) * bullets_speed)

Collision detection

When a bullet collides with a body or an area, the best way to get the data of the colliding bullet is to connect to the area_shape_entered signal.
In this example Bullets is an autoload.

func _on_area_shape_entered(area_id, _area, area_shape, _local_shape):
	if not Bullets.is_bullet_existing(area_id, area_shape):
		# The colliding area is not a bullet, returning.
		return

	# Get a BulletID from the area_shape passed in by the engine.
	var bullet_id = Bullets.get_bullet_from_shape(area_id, area_shape)

	# Get bullet properties, transform, velocity, lifetime etc.
	var bullet_transform = Bullets.get_bullet_property(bullet_id, "transform")
	# If you previously set a custom Dictionary containing the `damage` key as the data property, you can retrieve it.
	var bullet_damage = Bullet.get_bullet_property(bullet_id, "data").damage

	# You can also retrieve the BulletKit that generated the bullet and get/set its properties.
	var kit_collision_shape = Bullets.get_kit_from_bullet(bullet_id).collision_shape

	# Remove the bullet, call_deferred is necessary because the Physics2DServer is in its flushing state during callbacks.
	Bullets.call_deferred("release_bullet", bullet_id)

Reference

The plugin has two main components, explained below:

@ BulletKit

This is the resource used to configure each type of bullet.
Every BulletKit spawns its own bullet instances that support different kinds of properties.

The plugin comes with 4 base variants that can be customized via the editor:

BasicBulletKit
This is the most basic BulletKit, makes bullets move, generally at constant speed.
It's configurable with:
  • texture: controls what texture is sent to the bullet material.
  • material: the material used to render each bullet.
  • collisions_enabled: enables or disables collision detection, turning it off increases performances.
  • collision_layer_: the collision layer to use during collision detection. Visible only if collisions_enabled is on.
  • collision_mask: the collision mask to use during collision detection. Visible only if collisions_enabled is on.
  • collision_shape: the CollisionShape to use during collision detection. Visible only if collisions_enabled is on.
  • use_viewport_as_active_rect: if enabled, uses the current viewport to detect whether a bullet should be deleted.
  • active_rect: the rect outside of which the bullets get deleted. Visible only if use_viewport_as_active_rect if off.
  • rotate: controls whether the bullets automatically rotate based on their direction of travel.
  • unique_modulate_component: controls which modulate component in the material will be used as a unique value for each bullet instance. This can be used to offset bullets animation frames by unique amounts inside shaders and it's needed due to Godot not supporting material instance properties in 3.x.
  • data: custom data you can assign to the BulletKit.

Bullets spawned by a BasicBulletKit have those properties:

  • item_rid: the bullet canvas item RID, used internally. Read-only.
  • cycle: the number of times the bullet was recycled, used internally. Read-only.
  • shape_index: the index of the collision shape used by this bullet, used internally. Read-only.
  • transform: the Transform2D used to position and rotate the bullet.
  • velocity: the Vector2 that will be used to update the bullet position.
  • lifetime: how much time the bullet has been alive.
  • data: custom data you can assign to any bullet.
FollowingBulletKit
This BulletKit lets you define a target node for each bullet and a turning speed used to chase a it around.
It's configurable with:
  • texture: controls what texture is sent to the bullet material.
  • bullets_turning_speed: the turning speed with which the bullets will rotate towards the target node.
  • material: the material used to render each bullet.
  • collisions_enabled: enables or disables collision detection, turning it off increases performances.
  • collision_layer_: the collision layer to use during collision detection. Visible only if collisions_enabled is on.
  • collision_mask: the collision mask to use during collision detection. Visible only if collisions_enabled is on.
  • collision_shape: the CollisionShape to use during collision detection. Visible only if collisions_enabled is on.
  • use_viewport_as_active_rect: if enabled, uses the current viewport to detect whether a bullet should be deleted.
  • active_rect: the rect outside of which the bullets get deleted. Visible only if use_viewport_as_active_rect if off.
  • rotate: controls whether the bullets automatically rotate based on their direction of travel.
  • unique_modulate_component: controls which modulate component in the material will be used as a unique value for each bullet instance. This can be used to offset bullets animation frames by unique amounts inside shaders and it's needed due to Godot not supporting material instance properties in 3.x.
  • data: custom data you can assign to the BulletKit.

Bullets spawned by a FollowingBulletKit have those properties:

  • target_node: the Node2D the bullet will chase.
  • item_rid: the bullet canvas item RID, used internally. Read-only.
  • cycle: the number of times the bullet was recycled, used internally. Read-only.
  • shape_index: the index of the collision shape used by this bullet, used internally. Read-only.
  • transform: the Transform2D used to position and rotate the bullet.
  • velocity: the Vector2 that will be used to update the bullet position.
  • lifetime: how much time the bullet has been alive.
  • data: custom data you can assign to any bullet.
DynamicBulletKit
Lets you define bullets that change their behaviour based on their lifetime.
It's configurable with:
  • texture: controls what texture is sent to the bullet material.
  • lifetime_curves_span: the reference lifespan used by the curves to determine their current value.
  • lifetime_curves_loop: controls whether the curves will loop around when lifetime goes past lifetime_curves_span.
  • speed_multiplier_over_lifetime: controls the bullet speed multiplying its velocity magnitude by the value defined in this curve, based on the bullet lifetime.
  • rotation_offset_over_lifetime: controls the bullet rotation offsetting its initial rotation by the value in radians defined in this curve, based on the bullet lifetime.
  • material: the material used to render each bullet.
  • collisions_enabled: enables or disables collision detection, turning it off increases performances.
  • collision_layer_: the collision layer to use during collision detection. Visible only if collisions_enabled is on.
  • collision_mask: the collision mask to use during collision detection. Visible only if collisions_enabled is on.
  • collision_shape: the CollisionShape to use during collision detection. Visible only if collisions_enabled is on.
  • use_viewport_as_active_rect: if enabled, uses the current viewport to detect whether a bullet should be deleted.
  • active_rect: the rect outside of which the bullets get deleted. Visible only if use_viewport_as_active_rect if off.
  • rotate: controls whether the bullets automatically rotate based on their direction of travel.
  • unique_modulate_component: controls which modulate component in the material will be used as a unique value for each bullet instance. This can be used to offset bullets animation frames by unique amounts inside shaders and it's needed due to Godot not supporting material instance properties in 3.x.
  • data: custom data you can assign to the BulletKit.

Bullets spawned by a DynamicBulletKit have those properties:

  • transform: the Transform2D used to position and rotate the bullet.
  • starting_transform: the baseline Transform2D, curves will apply their changes based on this transform. This is automatically set when you manually edit transform.
  • velocity: the Vector2 that will be used to update the bullet position.
  • starting_speed: the baseline speed, curves will apply their changes based on this speed value. This is automatically set when you manually edit velocity.
  • item_rid: the bullet canvas item RID, used internally. Read-only.
  • cycle: the number of times the bullet was recycled, used internally. Read-only.
  • shape_index: the index of the collision shape used by this bullet, used internally. Read-only.
  • lifetime: how much time the bullet has been alive.
  • data: custom data you can assign to any bullet.
FollowingDynamicBulletKit
Lets you define bullets that change their chasing behaviour based on their lifetime, their distance to the target, or their angle to the target.
It's configurable with:
  • texture: controls what texture is sent to the bullet material.
  • lifetime_curves_span: the reference lifespan used by the curves to determine their current value. Only used when mode Based On Lifetime is selected on a curve.
  • distance_curves_span: the reference max distance used by the curves to determine their current value. Only used when mode Based On Target Distance is selected on a curve.
  • lifetime_curves_loop: controls whether the curves will loop around when lifetime goes past lifetime_curves_span. Only used when mode Based On Lifetime is selected on a curve.
  • speed_control_mode: specifies the mode the speed multiplier curve will determine its value:
    • Based On Lifetime: the curve x axis will map to the lifetime of the bullet, from 0 to lifetime_curves_span.
    • Based On Target Distance: the curve x axis will map to the distance to the target, from 0 to distance_curves_span.
    • Based on Angle To Target: the curve x axis will map to the angle between the bullet velocity Vector2 and the Vector2 pointing from the bullet to the target node, from 0 to PI.
  • speed_multiplier: controls the bullet speed multiplying its velocity magnitude by the value defined in this curve, based on whathever is set in speed_control_mode.
  • turning_speed_control_mode: specifies the mode the turning speed curve will determine its value:
    • Based On Lifetime: the curve x axis will map to the lifetime of the bullet, from 0 to lifetime_curves_span.
    • Based On Target Distance: the curve x axis will map to the distance to the target, from 0 to distance_curves_span.
    • Based on Angle To Target: the curve x axis will map to the angle between the bullet velocity Vector2 and the Vector2 pointing from the bullet to the target node, from 0 to PI.
  • turning_speed: controls the bullet turning speed towards the target node, based on whathever is set in turning_speed_control_mode.
  • material: the material used to render each bullet.
  • collisions_enabled: enables or disables collision detection, turning it off increases performances.
  • collision_layer_: the collision layer to use during collision detection. Visible only if collisions_enabled is on.
  • collision_mask: the collision mask to use during collision detection. Visible only if collisions_enabled is on.
  • collision_shape: the CollisionShape to use during collision detection. Visible only if collisions_enabled is on.
  • use_viewport_as_active_rect: if enabled, uses the current viewport to detect whether a bullet should be deleted.
  • active_rect: the rect outside of which the bullets get deleted. Visible only if use_viewport_as_active_rect if off.
  • rotate: controls whether the bullets automatically rotate based on their direction of travel.
  • unique_modulate_component: controls which modulate component in the material will be used as a unique value for each bullet instance. This can be used to offset bullets animation frames by unique amounts inside shaders and it's needed due to Godot not supporting material instance properties in 3.x.
  • data: custom data you can assign to the BulletKit.

Bullets spawned by a FollowingDynamicBulletKit have those properties:

  • target_node: the Node2D the bullet will chase.
  • velocity: the Vector2 that will be used to update the bullet position.
  • starting_speed: the baseline speed, curves will apply their changes based on this speed value. This is automatically set when you manually edit velocity.
  • item_rid: the bullet canvas item RID, used internally. Read-only.
  • cycle: the number of times the bullet was recycled, used internally. Read-only.
  • shape_index: the index of the collision shape used by this bullet, used internally. Read-only.
  • transform: the Transform2D used to position and rotate the bullet.
  • lifetime: how much time the bullet has been alive.
  • data: custom data you can assign to any bullet.

@ Bullets

Bullets is the node used to spawn bullets into the scene.
It can be configured through the editor setting which kinds of bullets will be used, the pool sizes, the z indices and the collision layer/mask.

# Spawns a bullet using the passed BulletKit and setting the properties contained in the `properties` dictionary.
# Returns whether a bullet has been spawned successfully.
spawn_bullet(bullet_kit : BulletKit, properties : Dictionary) -> bool

# Spawns and returns an opaque ID of a bullet using the passed BulletKit.
obtain_bullet(bullet_kit : BulletKit) -> BulletID

# Attempts to delete the bullet referenced by the passed `bullet_id`. Returns whether the removal was successful.
release_bullet(bullet_id : BulletID) -> bool

# Returns whether the bullet referenced by `bullet_id` is still alive and valid.
is_bullet_valid(bullet_id : BulletID) -> bool

# Returns whether `kit` has been configured and is ready to be used in this Bullets instance.
is_kit_valid(kit : BulletKit) -> bool

# Returns the number of currently available bullets for the `kit` BulletKit.
get_available_bullets(kit : BulletKit) -> int

# Returns the number of currently active bullets for the `kit` BulletKit.
get_active_bullets(kit : BulletKit) -> int

# Returns the number of pooled bullets for the `kit` BulletKit.
get_pool_size(kit : BulletKit) -> int

# Returns the z index of the bulltes generated by the `kit` BulletKit.
get_z_index(kit : BulletKit) -> int

# Returns the total number of currently available bullets.
get_total_available_bullets() -> int

# Returns the total number of currently active bullets.
get_total_active_bullets() -> int

# Returns whether `area_rid` and `area_shape` represent a valid and active bullet.
is_bullet_existing(area_rid : RID, area_shape : int) -> BulletID

# Returns the opaque ID of a bullet based on its area RID and its shape index.
get_bullet_from_shape(area_rid : RID, area_shape : int) -> BulletID

# Returns the BulletKit that defined the bullet referenced by the passed `bullet_id`.
get_kit_from_bullet(bullet_id : BulletID) -> BulletKit

# Sets the indicated property of the bullet referenced by `bullet_id`.
set_bullet_property(bullet_id : BulletID, property : String, value : Variant) -> void

# Returns the indicated property of the bullet referenced by `bullet_id`.
get_bullet_property(bullet_id : BulletID, property : String) -> Variant

Compiling and extending the plugin

The plugin can be extended with new BulletKits that are more suitable to your specific use cases.
To do so, you have to download the entire repository together with submodules, write some C++ code and recompile the plugin.

git clone --recursive https://github.com/samdze/godot-native-bullets-plugin

New BulletKits can be added creating a new header file inside the src/kits directory. Here's an example.

("target_node", &CustomFollowingBullet::set_target_node, &CustomFollowingBullet::get_target_node, nullptr, GODOT_METHOD_RPC_MODE_DISABLED, GODOT_PROPERTY_USAGE_NO_INSTANCE_STATE, GODOT_PROPERTY_HINT_RESOURCE_TYPE, "Node2D"); } }; // Bullet kit definition. // Add your own properties, methods and exports. class CustomFollowingBulletKit : public BulletKit { // Godot requires you to add this macro to make this class work properly. GODOT_CLASS(CustomFollowingBulletKit, BulletKit) public: // Use this macro to configure this bullet kit. // Pass the BulletsPool type that will be used as the argument. BULLET_KIT(CustomFollowingBulletsPool) Ref texture; float bullets_turning_speed = 1.0f; static void _register_methods() { register_property >("texture", &CustomFollowingBulletKit::texture, Ref (), GODOT_METHOD_RPC_MODE_DISABLED, GODOT_PROPERTY_USAGE_DEFAULT, GODOT_PROPERTY_HINT_RESOURCE_TYPE, "Texture"); register_property ("bullets_turning_speed", &CustomFollowingBulletKit::bullets_turning_speed, 1.0f, GODOT_METHOD_RPC_MODE_DISABLED, GODOT_PROPERTY_USAGE_DEFAULT, GODOT_PROPERTY_HINT_RANGE, "0.0,128.0"); // Add this macro at the end of the _register_methods() method. // Pass this BulletKit type and the used Bullet type as arguments. BULLET_KIT_REGISTRATION(CustomFollowingBulletKit, CustomFollowingBullet) } }; // Bullets pool definition. // This is the class that will handle the logic linked to your custom BulletKit. // It must extend AbstractBulletsPool. class CustomFollowingBulletsPool : public AbstractBulletsPool { void _init_bullet(CustomFollowingBullet* bullet) { // Initialize your bullet however you like. } void _enable_bullet(CustomFollowingBullet* bullet) { // Runs when a bullet is obtained from the pool and is being enabled. // Reset the bullet lifetime. bullet->lifetime = 0.0f; Rect2 texture_rect = Rect2(-kit->texture->get_size() / 2.0f, kit->texture->get_size()); RID texture_rid = kit->texture->get_rid(); // Configure the bullet to draw the kit texture each frame. VisualServer::get_singleton()->canvas_item_add_texture_rect(bullet->item_rid, texture_rect, texture_rid); } void _disable_bullet(CustomFollowingBullet* bullet) { // Runs when a bullet is being removed from the scene. } bool _process_bullet(CustomFollowingBullet* bullet, float delta) { // Runs each frame for each bullet, here goes your update logic. if(bullet->target_node != nullptr) { // Find the rotation to the target node. Vector2 to_target = bullet->target_node->get_global_position() - bullet->transform.get_origin(); float rotation_to_target = bullet->velocity.angle_to(to_target); float rotation_value = Math::min(kit->bullets_turning_speed * delta, std::abs(rotation_to_target)); // Apply the rotation, capped to the max turning speed. bullet->velocity = bullet->velocity.rotated(Math::sign(rotation_to_target) * rotation_value); } // Apply velocity. bullet->transform.set_origin(bullet->transform.get_origin() + bullet->velocity * delta); if(!active_rect.has_point(bullet->transform.get_origin())) { // Return true if the bullet should be deleted. return true; } // Rotate the bullet based on its velocity if "rotate" is enabled. if(kit->rotate) { bullet->transform.set_rotation(bullet->velocity.angle()); } // Bullet is still alive, increase its lifetime. bullet->lifetime += delta; // Return false if the bullet should not be deleted yet. return false; } }; // Add this macro at the end of the file to automatically implement a few needed utilities. // Pass the BulletKit type and the BulletsPool type as arguments. BULLET_KIT_IMPLEMENTATION(CustomFollowingBulletKit, CustomFollowingBulletsPool) #endif ">
// src/kits/custom_following_bullet_kit.h

#ifndef CUSTOM_FOLLOWING_BULLET_KIT_H
#define CUSTOM_FOLLOWING_BULLET_KIT_H

#include <Texture.hpp>
#include <PackedScene.hpp>
#include <Node2D.hpp>
#include <SceneTree.hpp>
#include <cmath>

#include "../bullet_kit.h"

using namespace godot;


// Bullet definition.
// This is necessary only if your BulletKit needs custom efficiently accessible bullet properties.
class CustomFollowingBullet : public Bullet {
	// Godot requires you to add this macro to make this class work properly.
	GODOT_CLASS(CustomFollowingBullet, Bullet)
public:
	Node2D* target_node = nullptr;

	// the _init method must be defined.
	void _init() {}

	// Custom setter and getter, not needed.
	void set_target_node(Node2D* node) {
		target_node = node;
	}

	Node2D* get_target_node() {
		return target_node;
	}

	static void _register_methods() {
		// Registering an Object reference property with GODOT_PROPERTY_HINT_RESOURCE_TYPE and hint_string is just
		// a way to tell the editor plugin the type of the property, so that it can be viewed in the BulletKit inspector.
		register_property
        (
        "target_node",
			&CustomFollowingBullet::set_target_node,
			&CustomFollowingBullet::get_target_node, 
        nullptr,
			GODOT_METHOD_RPC_MODE_DISABLED, GODOT_PROPERTY_USAGE_NO_INSTANCE_STATE, GODOT_PROPERTY_HINT_RESOURCE_TYPE, 
        "Node2D");
	}
};


        // Bullet kit definition.

        // Add your own properties, methods and exports.

        class 
        CustomFollowingBulletKit : 
        public 
        BulletKit {
	
        // Godot requires you to add this macro to make this class work properly.
	
        GODOT_CLASS(CustomFollowingBulletKit, BulletKit)

        public:
	
        // Use this macro to configure this bullet kit.
	
        // Pass the BulletsPool type that will be used as the argument.
	
        BULLET_KIT(CustomFollowingBulletsPool)

	Ref
        
          texture;
	
         float bullets_turning_speed = 
         1.
         0f;

	
         static 
         void 
         _register_methods() {
		register_property
         
          >(
          "texture", &CustomFollowingBulletKit::texture, Ref
          
           (),
			GODOT_METHOD_RPC_MODE_DISABLED, GODOT_PROPERTY_USAGE_DEFAULT, GODOT_PROPERTY_HINT_RESOURCE_TYPE, 
           "Texture");
		register_property
           
            float>(
            "bullets_turning_speed", &CustomFollowingBulletKit::bullets_turning_speed, 
            1.
            0f,
			GODOT_METHOD_RPC_MODE_DISABLED, GODOT_PROPERTY_USAGE_DEFAULT, GODOT_PROPERTY_HINT_RANGE, 
            "0.0,128.0");

		
            // Add this macro at the end of the _register_methods() method.
		
            // Pass this BulletKit type and the used Bullet type as arguments.
		
            BULLET_KIT_REGISTRATION(CustomFollowingBulletKit, CustomFollowingBullet)
	}
};


            // Bullets pool definition.

            // This is the class that will handle the logic linked to your custom BulletKit.

            // It must extend AbstractBulletsPool.

            class 
            CustomFollowingBulletsPool : 
            public 
            AbstractBulletsPool
            
              { 
             void 
             _init_bullet(CustomFollowingBullet* bullet) { 
             // Initialize your bullet however you like. } 
             void 
             _enable_bullet(CustomFollowingBullet* bullet) { 
             // Runs when a bullet is obtained from the pool and is being enabled. 
             // Reset the bullet lifetime. bullet->
             lifetime = 
             0.
             0f; Rect2 texture_rect = 
             Rect2(-kit->
             texture->
             get_size() / 
             2.
             0f, kit->
             texture->
             get_size()); RID texture_rid = kit->
             texture->
             get_rid(); 
             // Configure the bullet to draw the kit texture each frame. 
             VisualServer::get_singleton()->
             canvas_item_add_texture_rect(bullet->
             item_rid, texture_rect, texture_rid); } 
             void 
             _disable_bullet(CustomFollowingBullet* bullet) { 
             // Runs when a bullet is being removed from the scene. } 
             bool 
             _process_bullet(CustomFollowingBullet* bullet, 
             float delta) { 
             // Runs each frame for each bullet, here goes your update logic. 
             if(bullet->
             target_node != 
             nullptr) { 
             // Find the rotation to the target node. Vector2 to_target = bullet->
             target_node->
             get_global_position() - bullet->
             transform.
             get_origin(); 
             float rotation_to_target = bullet->
             velocity.
             angle_to(to_target); 
             float rotation_value = 
             Math::min(kit->
             bullets_turning_speed * delta, 
             std::abs(rotation_to_target)); 
             // Apply the rotation, capped to the max turning speed. bullet->
             velocity = bullet->
             velocity.
             rotated(
             Math::sign(rotation_to_target) * rotation_value); } 
             // Apply velocity. bullet->
             transform.
             set_origin(bullet->
             transform.
             get_origin() + bullet->
             velocity * delta); 
             if(!active_rect.
             has_point(bullet->
             transform.
             get_origin())) { 
             // Return true if the bullet should be deleted. 
             return 
             true; } 
             // Rotate the bullet based on its velocity if "rotate" is enabled. 
             if(kit->
             rotate) { bullet->
             transform.
             set_rotation(bullet->
             velocity.
             angle()); } 
             // Bullet is still alive, increase its lifetime. bullet->
             lifetime += delta; 
             // Return false if the bullet should not be deleted yet. 
             return 
             false; } }; 
             // Add this macro at the end of the file to automatically implement a few needed utilities. 
             // Pass the BulletKit type and the BulletsPool type as arguments. 
             BULLET_KIT_IMPLEMENTATION(CustomFollowingBulletKit, CustomFollowingBulletsPool) #
             endif
            
           
          
         
        
       

Next, register you Godot classes inside the gdlibrary.cpp file.

(); godot::register_class (); } ">
// src/gdlibrary.cpp

#include "bullets.h"
...
...

#include "kits/custom_following_bullet_kit.h"

...
...

extern "C" void GDN_EXPORT godot_nativescript_init(void *handle) {
	...
	...

	// Custom Bullet Kits.
	godot::register_class
    ();
	godot::register_class
    
     ();
}
    
   

Compile the bindings and the plugin for your selected platform.

cd addons/native_bullets/godot-cpp
scons platform=windows target=release generate_bindings=yes -j4

cd ..
scons platform=windows target=release
Issues
  • I fail to use it

    I fail to use it

    Hi, I would like to use this plugin (I guess it's not a module) and I failed. And I'm using linux.

    First, it try to just download the file and launch the project.godot that include an example, hit [F5] and nothing appear.

    Then, I try to compile the plugin myself but you didn't explain what is needed for that, or reference the official documentation for that. Trying to compile the plugin give me include error like Physics2DServer.hpp: No such file or directory. I also discover from the source code of godot that this file is now renamed to PhysicsServer2D.hpp.

    I tried with the official gdnative example and it's working but it don't include files from the source of godot.

    So, what is the require steps to be able to make your plugin?

    opened by moechofe 7
  • client crashes when adding the bullet kit resource to the Bullets node

    client crashes when adding the bullet kit resource to the Bullets node

    I made a Bullet scene, made it an autoload, attached bullets.gdns and added the bullet kit resource as shown: Clipboard01

    At this point trying to load the main scene (which is empty) causes the preview to crash without logging an error. If I don't add the resource, the scene loads. basic_bullet_kit.tres looks like this in the inspector:

    Clipboard01

    I'm using the godot icon.png as a test bullet if it matters.

    opened by kennethrapp 5
  • Plugin crashes when using a BulletKit with no collision_shape assigned

    Plugin crashes when using a BulletKit with no collision_shape assigned

    Assigning a BulletKit without a collision_shape to a BulletsEnvironment and playing the scene crashes the game, even if the BulletKit has collisions disabled.

    The fix is ready but it will take a while for me to update the repository.

    Temporary workaround: assign a collision shape to BulletKits even if they should have collisions disabled. Check collisions_enabled, assign a collision shape and uncheck it.

    opened by samdze 1
  • Question about HTML5 export performance

    Question about HTML5 export performance

    Lets say we had a test bullet hell in pure gdscript and also another test using your plugin and both exported to HTML5 for the web. How much more powerful would the C++ plugin be compared to just using gdscript? It would help me to know how much more critical performance using C++ number crunching compared to just using regular gdscript.

    opened by jointri 1
  • Bullets physics questions, Area or KinematicBody, tunneling

    Bullets physics questions, Area or KinematicBody, tunneling

    I think I'll end up replacing a lot of my particle systems with this... one bullet question though: this seems to all be area2d and not kinematic right?

    opened by dmaz 3
  • Make a Godot 4.0 compatible version of the plugin

    Make a Godot 4.0 compatible version of the plugin

    Wow... This is super nice, great job! I just started moving my projects over to 4 and was wondering if you had any plans in the near future to add a v4 branch for this?

    opened by dmaz 1
Owner
Samuele Zolfanelli
Samuele Zolfanelli
A dx12 river renderer using wave particles with interactive vortices.

Wave Particles with Interactive Vortices Final Result Overview In game industry water can be divided into two domains, ocean and river. This project f

ACskyline 207 Jul 27, 2022
This is a fast module to probing an area in a 2d plane for physic objects

Godot AreaProber 2D Checking for neighbour colliders made easy AreaProber allows you to probe for colliders anywhere in your 2D game's world, no need

Strauji 8 Feb 14, 2022
Source Code for "Ray Tracing Gems: High-Quality and Real-Time Rendering with DXR and Other APIs" by Eric Haines and Tomas Akenine-Möller

Apress Source Code This repository accompanies Ray Tracing Gems: High-Quality and Real-Time Rendering with DXR and Other APIs by Eric Haines and Tomas

Apress 823 Aug 2, 2022
Open source Altium Database Library with over 147,000 high quality components and full 3d models.

Open source Altium Database Library with over 147,000 high quality components and full 3d models.

Mark 1.2k Jul 27, 2022
GLSL and ESSL are Khronos high-level shading languages.

GLSL GLSL and ESSL are Khronos high-level shading languages. Khronos Registries are available for OpenGL OpenGL ES Vulkan Extension specifications in

The Khronos Group 235 Aug 6, 2022
The DirectX Shader Compiler project includes a compiler and related tools used to compile High-Level Shader Language (HLSL) programs into DirectX Intermediate Language (DXIL) representation

DirectX Shader Compiler The DirectX Shader Compiler project includes a compiler and related tools used to compile High-Level Shader Language (HLSL) pr

Microsoft 2.3k Aug 7, 2022
A library for high-performance, modern 2D graphics with SDL written in C.

SDL_gpu, a library for making hardware-accelerated 2D graphics easy. by Jonathan Dearborn SDL_gpu is licensed under the terms of the MIT License. See

Jonathan Dearborn 1k Aug 3, 2022
High frequency trading bot for crypto currencies

Gamma Ray WARNING: The author of this software will not be responsible for your losses on the market, use at your own discretion. Introduction Gamma R

TIAN Liang Yuan 220 Aug 10, 2022
⚡High-performance rendering for python

ZenGL ZenGL is a minimalist Python module providing exactly one way to render scenes with OpenGL. pip install zengl Documentation zengl on Github zen

Szabolcs Dombi 125 Aug 4, 2022
This Project Implement an interactive camera for 3D model using Quaternion. It have some advantages over eulerian camera like no gimbal lock and faster to compute.

Quaternion-Camera This Project Implement an interactive camera for 3D model using Quaternion. It have some advantages over eulerian camera like no gim

Phan Sang 6 Jul 30, 2022
Blend text in a HLSL shader and have it look like native DirectWrite

dwrite-hlsl This project demonstrates how to blend text in a HLSL shader and have it look like native DirectWrite. License This project is an extract

Leonard Hecker 11 May 24, 2022
A header-only C-like shading language compiler that writes Metal, HLSL, GLSL

GPUC A generic shading language compiler that writes metal, HLSL, and GLSL GPUC is a work in progress, not ready for prime time. The primary motivatio

Garett Bass 60 Aug 6, 2022
Horde3D is a small 3D rendering and animation engine. It is written in an effort to create an engine being as lightweight and conceptually clean as possible.

Horde3D Horde3D is a 3D rendering engine written in C++ with an effort being as lightweight and conceptually clean as possible. Horde3D requires a ful

Volker Vogelhuber 1.3k Aug 5, 2022
Lightweight and modular C++11 graphics middleware for games and data visualization

Magnum — Lightweight and modular C++11/C++14 graphics middleware for games and data visualization Looking for an open-source library that gives you gr

Vladimír Vondruš 4.1k Aug 4, 2022
ANSI C library for NURBS, B-Splines, and Bézier curves with interfaces for C++, C#, D, Go, Java, Lua, Octave, PHP, Python, R, and Ruby.

TinySpline TinySpline is a small, yet powerful library for interpolating, transforming, and querying arbitrary NURBS, B-Splines, and Bézier curves. Th

Marcel Steinbeck 810 Aug 7, 2022
Real-Time SLAM for Monocular, Stereo and RGB-D Cameras, with Loop Detection and Relocalization Capabilities

Real-Time SLAM for Monocular, Stereo and RGB-D Cameras, with Loop Detection and Relocalization Capabilities

Raul Mur-Artal 7.5k Aug 11, 2022
A C++/DirectX 11 implementation of "A Scalable and Production Ready Sky and Atmosphere Rendering Technique"

Atmosphere Renderer A C++/DirectX 11 implementation of "A Scalable and Production Ready Sky and Atmosphere Rendering Technique" Features interactive e

Z Guan 30 Aug 2, 2022
StereoKit is an easy-to-use open source mixed reality library for building HoloLens and VR applications with C# and OpenXR!

StereoKit is an easy-to-use open source mixed reality library for building HoloLens and VR applications with C# and OpenXR! Inspired by libraries like XNA and Processing, StereoKit is meant to be fun to use and easy to develop with, yet still quite capable of creating professional and business ready software.

Nick Klingensmith 668 Aug 8, 2022
FFVideo - an example FFmpeg lib, and wxWidgets Player with video filters and face detection

An example FFmpeg lib, and wxWidgets Player application with video filters and face detection, it is a no-audio video player intended for video experiments and developers learning how to code media applications.

Blake Senftner 20 Mar 26, 2022