bullets.gd 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. extends Node2D
  2. # This demo is an example of controling a high number of 2D objects with logic
  3. # and collision without using nodes in the scene. This technique is a lot more
  4. # efficient than using instancing and nodes, but requires more programming and
  5. # is less visual. Bullets are managed together in the `bullets.gd` script.
  6. const BULLET_COUNT = 500
  7. const SPEED_MIN = 20
  8. const SPEED_MAX = 80
  9. const bullet_image = preload("res://bullet.png")
  10. var bullets := []
  11. var shape
  12. class Bullet:
  13. var position = Vector2()
  14. var speed = 1.0
  15. # The body is stored as a RID, which is an "opaque" way to access resources.
  16. # With large amounts of objects (thousands or more), it can be significantly
  17. # faster to use RIDs compared to a high-level approach.
  18. var body = RID()
  19. func _ready():
  20. shape = PhysicsServer2D.circle_shape_create()
  21. # Set the collision shape's radius for each bullet in pixels.
  22. PhysicsServer2D.shape_set_data(shape, 8)
  23. for _i in BULLET_COUNT:
  24. var bullet = Bullet.new()
  25. # Give each bullet its own random speed.
  26. bullet.speed = randf_range(SPEED_MIN, SPEED_MAX)
  27. bullet.body = PhysicsServer2D.body_create()
  28. PhysicsServer2D.body_set_space(bullet.body, get_world_2d().get_space())
  29. PhysicsServer2D.body_add_shape(bullet.body, shape)
  30. # Don't make bullets check collision with other bullets to improve performance.
  31. PhysicsServer2D.body_set_collision_mask(bullet.body, 0)
  32. # Place bullets randomly on the viewport and move bullets outside the
  33. # play area so that they fade in nicely.
  34. bullet.position = Vector2(
  35. randf_range(0, get_viewport_rect().size.x) + get_viewport_rect().size.x,
  36. randf_range(0, get_viewport_rect().size.y)
  37. )
  38. var transform2d = Transform2D()
  39. transform2d.origin = bullet.position
  40. PhysicsServer2D.body_set_state(bullet.body, PhysicsServer2D.BODY_STATE_TRANSFORM, transform2d)
  41. bullets.push_back(bullet)
  42. func _process(_delta):
  43. # Order the CanvasItem to update every frame.
  44. queue_redraw()
  45. func _physics_process(delta):
  46. var transform2d = Transform2D()
  47. var offset = get_viewport_rect().size.x + 16
  48. for bullet in bullets:
  49. bullet.position.x -= bullet.speed * delta
  50. if bullet.position.x < -16:
  51. # Move the bullet back to the right when it left the screen.
  52. bullet.position.x = offset
  53. transform2d.origin = bullet.position
  54. PhysicsServer2D.body_set_state(bullet.body, PhysicsServer2D.BODY_STATE_TRANSFORM, transform2d)
  55. # Instead of drawing each bullet individually in a script attached to each bullet,
  56. # we are drawing *all* the bullets at once here.
  57. func _draw():
  58. var offset = -bullet_image.get_size() * 0.5
  59. for bullet in bullets:
  60. draw_texture(bullet_image, bullet.position + offset)
  61. # Perform cleanup operations (required to exit without error messages in the console).
  62. func _exit_tree():
  63. for bullet in bullets:
  64. PhysicsServer2D.free_rid(bullet.body)
  65. PhysicsServer2D.free_rid(shape)
  66. bullets.clear()