Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- extends Node2D
- class_name BeeSwarmManager
- @export var bee_texture : Texture
- @export var swarm_size : int = 800
- @export var spawn_radius : float = 1000.0
- @export_range(0, 2000, 10) var steer_force: float = 210.0
- @export_range(0.0, 10.0, 0.1) var linear_damping: float = 3.0
- @export var follow_target: NodePath
- @export_range(0.1, 50, 0.1) var bee_radius: float = 6.0
- @export_range(0.05, 2.0, 0.01) var bee_sprite_scale: float = 0.25
- @export_range(0.0, 500.0, 1.0) var min_distance_to_target: float = 20.0
- # separation tuning (fast, sample‐based)
- @export_range(1, 10, 1) var sep_samples : int = 3
- @export_range(0.0, 100.0, 1.0) var separation_distance: float = 20.0
- @export_range(0.0, 5000.0, 10.0) var separation_force: float = 800.0
- # low-level RIDs
- var _space_rid: RID
- var _canvas_rid: RID
- var _body_rids: Array[RID] = []
- var _shape_rids: Array[RID] = []
- var _item_rids: Array[RID] = []
- const BEE_LAYER_BIT = 0 # all bees get put on layer 1
- func _ready() -> void:
- randomize()
- _space_rid = get_world_2d().space
- _canvas_rid = get_canvas_item()
- for i in swarm_size:
- _spawn_enemy()
- func _physics_process(_delta: float) -> void:
- var target_node = get_node_or_null(follow_target)
- if not target_node:
- return
- var tpos = target_node.global_position
- var count = _body_rids.size()
- for i in count:
- var body_rid = _body_rids[i]
- # 1) read position
- var st = PhysicsServer2D.body_get_state(
- body_rid, PhysicsServer2D.BODY_STATE_TRANSFORM
- )
- var pos = st.origin
- # 2) steer toward target if outside guard radius
- var diff = tpos - pos
- var dist = diff.length()
- var rot: float
- if dist > min_distance_to_target:
- var dir = diff / dist
- PhysicsServer2D.body_apply_central_force(body_rid, dir * steer_force)
- rot = dir.angle()
- else:
- rot = diff.angle()
- # 3) approximate separation (O(k⋅N))
- if count > 1 and sep_samples > 0:
- for s in sep_samples:
- var j = randi() % count
- if j == i:
- continue
- var other_st = PhysicsServer2D.body_get_state(
- _body_rids[j], PhysicsServer2D.BODY_STATE_TRANSFORM
- )
- var other_pos = other_st.origin
- var delta = pos - other_pos
- var d = delta.length()
- if d > 0.0 and d < separation_distance:
- var push_dir = delta / d
- PhysicsServer2D.body_apply_central_force(
- body_rid,
- push_dir * separation_force
- )
- # 4) update sprite
- var ci_rid = _item_rids[i]
- var xform = Transform2D().rotated(rot).translated(pos)
- RenderingServer.canvas_item_set_transform(ci_rid, xform)
- func _spawn_enemy() -> void:
- var body = PhysicsServer2D.body_create()
- PhysicsServer2D.body_set_collision_layer(body, BEE_LAYER_BIT)
- PhysicsServer2D.body_set_collision_mask(body, BEE_LAYER_BIT)
- PhysicsServer2D.body_set_mode(body, PhysicsServer2D.BODY_MODE_RIGID)
- PhysicsServer2D.body_set_space(body, _space_rid)
- # disable gravity
- PhysicsServer2D.body_set_param(
- body,
- PhysicsServer2D.BODY_PARAM_GRAVITY_SCALE,
- 0.0
- )
- # apply linear damping
- PhysicsServer2D.body_set_param(
- body,
- PhysicsServer2D.BODY_PARAM_LINEAR_DAMP,
- linear_damping
- )
- # shape
- var shape = PhysicsServer2D.circle_shape_create()
- PhysicsServer2D.shape_set_data(shape, bee_radius)
- PhysicsServer2D.body_add_shape(body, shape, Transform2D.IDENTITY)
- _body_rids .append(body)
- _shape_rids.append(shape)
- # sprite via RenderingServer
- var ci = RenderingServer.canvas_item_create()
- RenderingServer.canvas_item_set_parent(ci, _canvas_rid)
- var tex_sz = bee_texture.get_size() * bee_sprite_scale
- var rect = Rect2(-tex_sz / 2, tex_sz)
- RenderingServer.canvas_item_add_texture_rect(ci, rect, bee_texture)
- _item_rids.append(ci)
- # random start
- var start = Vector2(
- randf_range(-spawn_radius, spawn_radius),
- randf_range(-spawn_radius, spawn_radius)
- )
- var xf = Transform2D.IDENTITY.translated(start)
- PhysicsServer2D.body_set_state(
- body,
- PhysicsServer2D.BODY_STATE_TRANSFORM,
- xf
- )
- RenderingServer.canvas_item_set_transform(ci, xf)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement