Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- extends Spatial
- var packed_scenes := []
- var instances := []
- var projectiles := []
- var index_offsets := []
- var test := []
- var multimeshes := []
- var is_active := true
- var time := 0.0
- func _process(_delta : float) -> void:
- # if not Engine.get_idle_frames() % 2 == 0:
- # return
- for i in index_offsets.size():
- index_offsets[i] = 0
- if projectiles.empty():
- return
- for i in projectiles.size():
- if projectiles[i].empty():
- continue
- # if not is_active:
- # continue
- for j in projectiles[i].size():
- j -= index_offsets[i] # смещение по индексу, нужно после удалении объекта
- var direct_state_transform : Transform
- if projectiles[i][j].physical_body.deleted:
- direct_state_transform = projectiles[i][j].physical_body.last_info.transform
- else:
- var body_rid : RID = projectiles[i][j].physical_body.body_rid
- direct_state_transform = PhysicsServer.body_get_direct_state(body_rid).transform
- var multimesh : MultiMesh = multimeshes[i].multimesh
- var offset_transform : Transform = multimeshes[i].get_meta("offset_transform")
- multimesh.set_instance_transform(j, direct_state_transform * offset_transform)
- func _physics_process(_delta : float) -> void:
- for i in index_offsets.size():
- index_offsets[i] = 0
- if projectiles.empty():
- return
- for i in projectiles.size():
- if projectiles[i].empty():
- continue
- for j in projectiles[i].size():
- j -= index_offsets[i]
- # удаление узла по истечению н-ого времени и если это значение больше нуля
- if projectiles[i][j].meta_data.life_time > 0 and \
- Global.time >= projectiles[i][j].meta_data.init_time + \
- projectiles[i][j].meta_data.life_time:
- _delete_projectile(i, j)
- continue
- if projectiles[i][j].physical_body.deleted:
- continue
- else:
- projectiles[i][j].physical_body.last_info.transform = projectiles[i][j].physical_body.direct_state.transform
- var direct_state : PhysicsDirectBodyState = projectiles[i][j].physical_body.direct_state
- if direct_state.transform.origin.y < -10:
- _delete_projectile(i, j)
- continue
- if direct_state.linear_velocity.length() < 0.01:
- _delete_physical_body(i, j)
- continue
- var contact_count : int = direct_state.get_contact_count() # получение количество столкновений
- if contact_count: # произошло столкновение
- if projectiles[i][j].meta_data.delete_on_impact:
- # удаление физ тела и меша, а после удаление из массива
- _delete_projectile(i, j)
- func projectile(packed_scene : PackedScene, spawn_transform : Transform, \
- collision_exceptions := [], _effects := []) -> void:
- var instance : Projectile
- var index := 0
- if packed_scenes.empty(): # добавление первого пакета, при отсуствуии коих
- _init_packed_scene(packed_scene)
- else: # поиск пакетов и получение индекса -1
- index = packed_scenes.find(packed_scene)
- if packed_scenes[index] != packed_scene: # если данный индекс -1
- _init_packed_scene(packed_scene)
- # поиск корректного индекса без -1, для последующего использования
- index = packed_scenes.find(packed_scenes[index])
- instance = instances[index]
- var instance_collision_shape : Shape = instance.get_node("Collision").shape
- var shape_form : int
- var shape_data := {}
- if instance_collision_shape is CapsuleShape:
- shape_form = PhysicsServer.SHAPE_CAPSULE
- shape_data = {"radius" : instance_collision_shape.radius, \
- "height" : instance_collision_shape.height}
- var rigid_body_data := {
- "mass" : instance.mass,
- "friction" : instance.physics_material_override.friction,
- "bounce" : instance.physics_material_override.bounce,
- "gravity_scale" : instance.gravity_scale,
- "contacts_reported" : instance.contacts_reported,
- "linear_velocity" : instance.linear_velocity,
- "linear_damp" : instance.linear_damp,
- "angular_velocity" : instance.angular_velocity,
- "angular_damp" : instance.angular_damp,
- "collision_layer" : instance.collision_layer,
- "collision_mask" : instance.collision_mask,}
- var impulse_data := {}
- if instance.random_impulse:
- impulse_data = { # рандомизация данные исходя из ограничений экземпляра
- "vector" : Vector3(\
- rand_range(instance.impulse_vector_random_range_x.x, \
- instance.impulse_vector_random_range_x.y), \
- rand_range(instance.impulse_vector_random_range_y.x, \
- instance.impulse_vector_random_range_y.y), \
- rand_range(instance.impulse_vector_random_range_z.x, \
- instance.impulse_vector_random_range_z.y)),
- "speed" : rand_range(instance.impulse_speed_random_range.x, \
- instance.impulse_speed_random_range.y)}
- else: # присваение стандартных значений без рандомизации
- impulse_data = {
- "vector" : instance.impulse_vector,
- "speed" : instance.impulse_speed}
- projectiles[index].append({
- "physical_body" : _physical_body(spawn_transform, shape_form, shape_data, \
- rigid_body_data, collision_exceptions, impulse_data),
- "meta_data" : {
- "delete_on_impact" : instance.delete_on_impact,
- "init_time" : Global.time,
- "life_time" : instance.life_time
- }
- })
- is_active = true
- multimeshes[index].multimesh.instance_count += 1
- # print(multimeshes[index].multimesh.instance_count)
- func _init_packed_scene(packed_scene : PackedScene) -> void:
- packed_scenes.append(packed_scene) # добавление
- var instance := packed_scene.instance()
- instances.append(instance)
- projectiles.append([]) # создание пустой массива в н-ом индексе
- index_offsets.append(0)
- test.append(0)
- var multimesh_name := str(instance.name) + "MultiMesh"
- var instance_mesh : MeshInstance = instance.get_node("Mesh")
- multimeshes.append(_add_multimesh(multimesh_name, {
- "cast_shadow" : instance_mesh.cast_shadow,
- "portal_mode" : instance_mesh.portal_mode,
- "offset_transform" : instance_mesh.transform,
- "mesh" : instance_mesh.mesh,
- }))
- func _physical_body(spawn_transform : Transform, shape_form : int, shape_data : Dictionary, \
- rigid_body_data : Dictionary, collision_exceptions : Array, impulse_data : Dictionary) -> Dictionary:
- var body_rid := PhysicsServer.body_create()
- var shape_rid = PhysicsServer.shape_create(shape_form)
- PhysicsServer.shape_set_data(shape_rid, shape_data)
- PhysicsServer.body_add_shape(body_rid, shape_rid, Transform())
- PhysicsServer.body_set_collision_layer(body_rid, rigid_body_data.collision_layer)
- PhysicsServer.body_set_collision_mask(body_rid, rigid_body_data.collision_mask)
- if not collision_exceptions.empty():
- for index in collision_exceptions:
- PhysicsServer.body_add_collision_exception(body_rid, index)
- PhysicsServer.body_set_mode(body_rid, PhysicsServer.BODY_MODE_RIGID)
- PhysicsServer.body_set_param(body_rid, PhysicsServer.BODY_PARAM_MASS, rigid_body_data.mass)
- PhysicsServer.body_set_param(body_rid, PhysicsServer.BODY_PARAM_FRICTION, rigid_body_data.friction)
- PhysicsServer.body_set_param(body_rid, PhysicsServer.BODY_PARAM_BOUNCE , rigid_body_data.bounce)
- PhysicsServer.body_set_param(body_rid, PhysicsServer.BODY_PARAM_GRAVITY_SCALE, rigid_body_data.gravity_scale)
- PhysicsServer.body_set_max_contacts_reported(body_rid, rigid_body_data.contacts_reported)
- PhysicsServer.body_set_state(body_rid, PhysicsServer.BODY_STATE_LINEAR_VELOCITY, rigid_body_data.linear_velocity)
- PhysicsServer.body_set_param(body_rid, PhysicsServer.BODY_PARAM_LINEAR_DAMP, rigid_body_data.linear_damp)
- PhysicsServer.body_set_state(body_rid, PhysicsServer.BODY_STATE_ANGULAR_VELOCITY, rigid_body_data.angular_velocity)
- PhysicsServer.body_set_param(body_rid, PhysicsServer.BODY_PARAM_ANGULAR_DAMP, rigid_body_data.angular_damp)
- PhysicsServer.body_set_state(body_rid, PhysicsServer.BODY_STATE_TRANSFORM, spawn_transform)
- PhysicsServer.body_set_state(body_rid, PhysicsServer.BODY_STATE_SLEEPING, true)
- PhysicsServer.body_set_state(body_rid, PhysicsServer.BODY_STATE_CAN_SLEEP, true)
- PhysicsServer.body_apply_central_impulse(body_rid, spawn_transform.basis * impulse_data.vector * impulse_data.speed)
- PhysicsServer.body_set_space(body_rid, get_world().space)
- var direct_state := PhysicsServer.body_get_direct_state(body_rid)
- return {
- "body_rid" : body_rid,
- "shape_rid" : shape_rid,
- "direct_state" : direct_state,
- "last_info" : {
- "transform" : null,
- },
- "deleted" : false,
- "deleted_bodies" : 0,
- }
- func _add_multimesh(new_name : String, data := {}) -> MultiMeshInstance:
- var multimesh_instance : MultiMeshInstance = MultiMeshInstance.new()
- multimesh_instance.name = new_name
- multimesh_instance.cast_shadow = data.cast_shadow
- multimesh_instance.portal_mode = data.portal_mode
- multimesh_instance.set_meta("offset_transform", data.offset_transform)
- get_parent().add_child(multimesh_instance)
- var new_multimesh := MultiMesh.new()
- new_multimesh.transform_format = MultiMesh.TRANSFORM_3D
- new_multimesh.mesh = data.mesh
- multimesh_instance.multimesh = new_multimesh
- return multimesh_instance
- func _delete_projectile(i : int, j : int) -> void:
- index_offsets[i] += 1
- if not projectiles[i][j].physical_body.deleted:
- PhysicsServer.free_rid(projectiles[i][j].physical_body.body_rid)
- PhysicsServer.free_rid(projectiles[i][j].physical_body.shape_rid)
- multimeshes[i].multimesh.instance_count -= 1
- projectiles[i].remove(j)
- test[i] -= 1
- if test[i] <= projectiles[i].size():
- is_active = true
- func _delete_physical_body(i : int, j : int) -> void:
- PhysicsServer.free_rid(projectiles[i][j].physical_body.body_rid)
- PhysicsServer.free_rid(projectiles[i][j].physical_body.shape_rid)
- projectiles[i][j].physical_body.deleted = true
- test[i] += 1
- if test[i] >= projectiles[i].size():
- is_active = false
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement