Breakout Clone 3: Destructible Blocks

2023-02-13

This one is pretty easy. Every time the ball collides with a block, we call a method on that block that destroys it. I may want to have blocks that take multiple hits before they're destroyed, so I'll call this method TakeHit and pass it a value representing how much "health" to take away from it.

In my Ball.cs script:

  void OnCollisionEnter2D(Collision2D collision) {
    string tag = collision.gameObject.tag;

    if (tag == "Block" || tag == "Wall" || tag == "Paddle") {
      Vector2 currentVelocity = rigidBody2D.velocity;

      // A vector perpendicular to the surface we're colliding with
      Vector2 normal = collision.GetContact(0).normal;

      // calculate the new, reflected velocity
      Vector2 newVelocity = Vector2.Reflect(currentVelocity, normal);

      rigidBody2D.velocity = newVelocity;
    }

    if (tag == "Block") {
      collision.gameObject.GetComponent<Block>().TakeHit(1);
    }

    if (tag == "Bottom Wall") {
      BottomHit();
    }
  }

Then, in a new Block.cs script that is attached to the Block object:

  public class Block : MonoBehaviour
  {
    [SerializeField] int initialHealth = 1;
    private int currentHealth;

    void Awake() {
      currentHealth = initialHealth;
    }

    public void TakeHit(int hpToRemove) {
      currentHealth -= hpToRemove;
      DestroyBlockIfDead();
    }

    private void DestroyBlockIfDead() {
      if (currentHealth > 0) {
        return
      }

      Destroy(gameObject);
    }
  }

Next I'm going to add a new level and transition to it when their are no blocks remaining in the current one. This is first time I'm going to need a singleton object that lives the entire length of game, so I'll call it GameSession.