## Exercise 1: Projectiles There are several ways we can create projectiles in Godot. To choose the right one we need to think about how the projectiles should behave. Consider the following: * Should there be a limited number of projectiles? * What happens to projectiles that leave the viewing area? * Should shots ricochet? * Do projectiles need momentum, acceleration, deceleration? Depending on what we need the projectiles to do, we could choose a body type for them. ### Area Node Bullet The area node is probably the simplest way to achieve a projectile. Areas can receive signals when a child collision shape intersects another collision shape (so they know when they have hit something). An area node also inherits a Transform, with a position property that can be written to. ``` extends Area2D var speed = 750 func setSpeed(speedVal): speed = speedVal func _physics_process(delta): position += transform.x * speed * delta func _on_body_entered(body): # blast the body? if body.is_in_group("boxes"): body.queue_free() queue_free() ``` Now to use our bullet we need to be able to create the bullet and position it with code. This is called instantiation. To be able to instantiate a scene in Godot we must pre-load it. `var bullet = preload("res://scenes/bullet.tscn")` We can now create as many isntances of the bullet as we wish! But be careful! When we add our bullet to the world, we want to add it at the global scope - not at the scope of the character. Otherwise, when the character moves the bullet will move with them. ``` if Input.is_action_just_pressed("blast"): var mybullet = bullet.instantiate() mybullet.setSpeed(-BLAST_SPEED if faceLeft else BLAST_SPEED) owner.add_child(mybullet) mybullet.transform = markerLeft.global_transform if faceLeft else markerRight.global_transform ``` ### RigidBody Missile For our next example, we will create our projectile from a RigidBody so that it can react via physics to the environment. One thing to note about RigidBodies is that they do not by default hear collision signals. This is a performance consideration, and usually this is a good thing, but in the case of our missile we want the RigidBody to know about the collision. For this reason in the inspector we will need to turn on collision_monitor and set a value in max_collision_objects. After this, we will be able to detect collisions. ``` extends RigidBody2D func _on_body_entered(body): # check here to see if the thing should explode print("missile hit something") if body.is_in_group("boxes"): body.queue_free() if not body.is_in_group("player"): queue_free() ``` As before, we need to think about instantiation of the missile. Depending on the direction the player is facing, we could either apply a negative or a positive impulse to the RigidBody. ``` if Input.is_action_just_pressed("blast"): var myMissile = missile.instantiate() owner.add_child(myMissile) myMissile.transform = markerLeft.global_transform if faceLeft else markerRight.global_transform var missileForce = -600 if faceLeft else 600 myMissile.apply_impulse(Vector2(missileForce,10), Vector2(0, 0)) ```