bullets.gd 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  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. randomize()
  21. shape = Physics2DServer.circle_shape_create()
  22. # Set the collision shape's radius for each bullet in pixels.
  23. Physics2DServer.shape_set_data(shape, 8)
  24. for _i in BULLET_COUNT:
  25. var bullet = Bullet.new()
  26. # Give each bullet its own speed.
  27. bullet.speed = rand_range(SPEED_MIN, SPEED_MAX)
  28. bullet.body = Physics2DServer.body_create()
  29. Physics2DServer.body_set_space(bullet.body, get_world_2d().get_space())
  30. Physics2DServer.body_add_shape(bullet.body, shape)
  31. # Don't make bullets check collision with other bullets to improve performance.
  32. # Their collision mask is still configured to the default value, which allows
  33. # bullets to detect collisions with the player.
  34. Physics2DServer.body_set_collision_layer(bullet.body, 0)
  35. # Place bullets randomly on the viewport and move bullets outside the
  36. # play area so that they fade in nicely.
  37. bullet.position = Vector2(
  38. rand_range(0, get_viewport_rect().size.x) + get_viewport_rect().size.x,
  39. rand_range(0, get_viewport_rect().size.y)
  40. )
  41. var transform2d = Transform2D()
  42. transform2d.origin = bullet.position
  43. Physics2DServer.body_set_state(bullet.body, Physics2DServer.BODY_STATE_TRANSFORM, transform2d)
  44. bullets.push_back(bullet)
  45. func _process(_delta):
  46. # Order the CanvasItem to update every frame.
  47. update()
  48. func _physics_process(delta):
  49. var transform2d = Transform2D()
  50. var offset = get_viewport_rect().size.x + 16
  51. for bullet in bullets:
  52. bullet.position.x -= bullet.speed * delta
  53. if bullet.position.x < -16:
  54. # The bullet has left the screen; move it back to the right.
  55. bullet.position.x = offset
  56. transform2d.origin = bullet.position
  57. Physics2DServer.body_set_state(bullet.body, Physics2DServer.BODY_STATE_TRANSFORM, transform2d)
  58. # Instead of drawing each bullet individually in a script attached to each bullet,
  59. # we are drawing *all* the bullets at once here.
  60. func _draw():
  61. var offset = -bullet_image.get_size() * 0.5
  62. for bullet in bullets:
  63. draw_texture(bullet_image, bullet.position + offset)
  64. # Perform cleanup operations (required to exit without error messages in the console).
  65. func _exit_tree():
  66. for bullet in bullets:
  67. Physics2DServer.free_rid(bullet.body)
  68. Physics2DServer.free_rid(shape)
  69. bullets.clear()