La rejouabilité du jeu !

Pour améliorer la rejouabilité il faut que le joueur puisse enchaîner les niveaux et également avoir des mécaniques qui font perdre le joueur pour le pousser à visser le meilleur score possible.

  • Créer un nouveau stage après la destruction de toutes les briques
  • Remise à zéro de la partie lorsque le joueur n’a plus de vies

Nouveau stage (niveau)

Lorsque toutes les briques sont détruites nous rajouterons une ligne supplémentaire à notre variable niveau.lignes pour augmenter la difficulté et donner du challenge au joueur.

Nous devons recréer les briques lorsque la balle n’est pas dans la zone des briques pour éviter des collisions non gérables.

Pour simplifier le code nous remettrons la balle sur la raquette pour éviter des collisions avec la balle pendant la création des briques.

Enfin nous rajouterons les nouvelles briques.

Pour savoir quand créer le prochain stage, nous devons tester la variable niveau.totalBriques

  • Vérifier si la valeur de niveau.totalBriques vaut 0

Si elle est bien à 0 Alors :

  • Replacer la balle sur la raquette
  • Repasser balle.isGlue à true
  • Augmenter la variable de niveau.lignes de +1
  • Recréer nos briques avec la fonction niveau.create()
function love.update(dt)

  -- collision entre la balle et les briques : 
  local x, y, w, h -- nos variables de positions et dimensions de nos briques
  x = 0
  y = 0
  w = 800 / 6
  h = 30
  for ligne=1, niveau.lignes do
    for colonne=1, niveau.colonnes do

      if briques[ligne][colonne] == 1 then -- on test la brique si celle-ci vaut 1

        -- test collision en X ?
        if balle.x + balle.w > x and balle.x < x + w then

          -- test collsion en Y ?
          if balle.y + balle.h > y and balle.y < y + h then
            balle.y = y+h
            balle.vy = 0 - balle.vy
            briques[ligne][colonne] = 0 -- ainsi la brique ne sera plus tester
            game.score = game.score + 10 -- on augmente le score de 10 points !
            niveau.totalBriques = niveau.totalBriques - 1 -- decompte des briques détruites
            if niveau.totalBriques == 0 then
              balle.x = raquette.x + ((raquette.w / 2) - (balle.w / 2)) -- remet la balle sur la raquette sur l axe X
              balle.y = raquette.y - (balle.h +  2) -- remetla balle sur la raquette sur l axe Y
              balle.isGlue = true -- replace la balle sur la raquette
              niveau.lignes = niveau.lignes + 1 -- on augmente la difficulte en ajouter une ligne à nos briques
              niveau.create() -- on recreer le tableau de briques avec de nouvelles valeurs
            end
          end
        end

      end

      x = x + w
    end
    x = 0
    y = y + h
  end

end

Remise à zéro en cas de défaite

Pour faire ceci nous allons créer une fonction game.new()

Cette fonction doit remettre toutes les valeurs par défaut, la position de la raquette et de la balle, les briques, le score, le nombre de lignes de notre niveau a sa valeur par défaut.

Nous allons donc rajouter des variables à notre table niveau pour connaître la valeur par défaut des lignes.

local niveau = {lignesDef=5, lignes=5, colonnes=6, totalBriques=0}

Pour la position de la raquette, nous allons proceder pareil.

local raquette = {xDef=300, yDef=555, x=300, y=555, w=200, h=40, speed=250}

Créer la fonction pour remettre le jeu à zero : game.new()

function niveau.create()

-- creation des briques
  for ligne=1, niveau.lignes do
    briques[ligne] = {}
    for colonne=1, niveau.colonnes do
      briques[ligne][colonne] = 1
    end
  end

  niveau.totalBriques = niveau.lignes * niveau.colonnes -- total de briques

end

Maintenant il ne reste plus qu’à ajouter notre condition à notre update.

Nous la placerons avec la detection de la balle avec le bors bas de l’ecran.

  • Vérifier si la valeur de game.vies vaut 0

Si elle est bien à 0 Alors :

  • Exécuter game.new()
function love.update(dt)
  
    -- la balle est perdue si elle a touchee le bord en bas
  if balle.y + balle.h > 600 then
    balle.isGlue = true
    balle.vy = -1
    balle.vx = -1
    game.vies = game.vies - 1 -- on enleve une vie au joueur
    if game.vies == 0 then
      game.new()
    end
  end
  
end

Voir le code complet :

love.window.setTitle("Casse Brique")

local raquette = {xDef=300, yDef=555, x=300, y=555, w=200, h=40, speed=250}

local balle = {x=0, y=0, w=40, h=40, isGlue=true, vx=-1, vy=-1, speed=300}

local briques = {} -- nos briques

local game = {score=0, vies=3}

local niveau = {lignesDef=5, lignes=5, colonnes=6, totalBriques=0}

function game.new()
  -- on remets la raquette au centre de l'ecran
  raquette.x = raquette.xDef
  raquette.y = raquette.yDef

  -- on remets la balle sur la raquette
  balle.x = raquette.x + ((raquette.w / 2) - (balle.w / 2))
  balle.y = raquette.y - (balle.h +  2)
  balle.isGlue = true

  -- on remets le score a 0
  game.score = 0

  -- remets a zero le nombre de lignes de briques
  niveau.lignes = niveau.lignesDef

  -- on recreer les briques pour une nouvelle partie
  niveau.create()
end
--

function niveau.create()

-- creation des briques
  for ligne=1, niveau.lignes do
    briques[ligne] = {}
    for colonne=1, niveau.colonnes do
      briques[ligne][colonne] = 1
    end
  end

  niveau.totalBriques = niveau.lignes * niveau.colonnes -- total de briques

end
--

function love.load()
  niveau.create()
end


function love.update(dt)
  if balle.isGlue == true then
    balle.x = raquette.x + ((raquette.w / 2) - (balle.w / 2))
    balle.y = raquette.y - (balle.h +  2)
  elseif balle.isGlue == false then
    balle.x = balle.x + (balle.vx * balle.speed * dt)
    balle.y = balle.y + (balle.vy * balle.speed * dt)
  end

  -- la balle rebondi sur le bord droit ou gauche
  if balle.x < 0 then
    balle.x = 0
    balle.vx = 0 - balle.vx
  elseif balle.x + balle.w > 800 then
    balle.x = 800 - balle.w
    balle.vx = 0 - balle.vx
  end

  -- la balle rebondi sur le bord en haut
  if balle.y < 0 then
    balle.y = 0
    balle.vy = 0 - balle.vy
  end

  -- la balle est perdue si elle a touchee le bord en bas
  if balle.y + balle.h > 600 then
    balle.isGlue = true
    balle.vy = -1
    balle.vx = -1
    game.vies = game.vies - 1 -- on enleve une vie au joueur
    if game.vies == 0 then
      game.new()
    end
  end

  -- deplacement de la raquette Droite ou Gauche
  if love.keyboard.isDown("left") then
    raquette.x = raquette.x - (raquette.speed * dt)
  elseif love.keyboard.isDown("right") then
    raquette.x = raquette.x + (raquette.speed * dt)
  end

  -- limiter le deplacement de la raquette a la fenetre du jeu
  if raquette.x < 0 then
    raquette.x = 0
  elseif raquette.x + raquette.w > 800 then
    raquette.x = 800 - raquette.w
  end

  -- collision balle avec raquette :
  -- test collision en X ?
  if balle.x + balle.w > raquette.x and balle.x < raquette.x + raquette.w then

    -- test collsion en Y ?
    if balle.y + balle.h > raquette.y then

      -- 1 | on replace la balle juste au dessus de la raquette
      balle.y = raquette.y - balle.h

      -- 2 | on inverse la direction VY de la balle
      balle.vy = 0 - balle.vy

    end

  end

  -- collision entre la balle et les briques : 
  local x, y, w, h -- nos variables de positions et dimensions de nos briques
  x = 0
  y = 0
  w = 800 / 6
  h = 30
  for ligne=1, niveau.lignes do
    for colonne=1, niveau.colonnes do

      if briques[ligne][colonne] == 1 then -- on test la brique si celle-ci vaut 1

        -- test collision en X ?
        if balle.x + balle.w > x and balle.x < x + w then

          -- test collsion en Y ?
          if balle.y + balle.h > y and balle.y < y + h then
            balle.y = y+h
            balle.vy = 0 - balle.vy
            briques[ligne][colonne] = 0 -- ainsi la brique ne sera plus tester
            game.score = game.score + 10 -- on augmente le score de 10 points !
            niveau.totalBriques = niveau.totalBriques - 1 -- decompte des briques détruites
            if niveau.totalBriques == 0 then
              balle.x = raquette.x + ((raquette.w / 2) - (balle.w / 2)) -- remet la balle sur la raquette sur l axe X
              balle.y = raquette.y - (balle.h +  2) -- remetla balle sur la raquette sur l axe Y
              balle.isGlue = true -- replace la balle sur la raquette
              niveau.lignes = niveau.lignes + 1 -- on augmente la difficulte en ajouter une ligne à nos briques
              niveau.create() -- on recreer le tableau de briques avec de nouvelles valeurs
            end
          end
        end

      end

      x = x + w
    end
    x = 0
    y = y + h
  end

end
--

function love.draw()

  -- notre raquette
  love.graphics.rectangle("fill", raquette.x, raquette.y, raquette.w, raquette.h)

  -- notre balle
  love.graphics.rectangle("fill", balle.x, balle.y, balle.w, balle.h)

  local x, y, w, h -- nos variables briques
  x = 0
  y = 0
  w = 800 / 6
  h = 30

  for ligne=1, niveau.lignes do

    for colonne=1, niveau.colonnes do
      if briques[ligne][colonne] == 1 then -- on affiche la brique si celle-ci vaut 1
        love.graphics.rectangle("fill", x+1, y+1, w-2, h-2)
      end
      x = x + w -- a chaque colonne on decale notre variable x de la largeur d une brique
    end

    x = 0 -- on remets la position x pour la ligne suivante
    y = y + h -- on decalle la position y pour la ligne suivante
  end

  -- le score
  love.graphics.setColor(0,0,1,1) -- red, green, blue, alpha
  love.graphics.print("Score : "..game.score, 10, 8)
  love.graphics.setColor(1,1,1,1) -- on remets la couleur par defaut pour la suite des appels

  -- les vies
  love.graphics.setColor(0,0,1,1) -- red, green, blue, alpha
  love.graphics.print("Vies restantes : "..game.vies, 680, 8)
  love.graphics.setColor(1,1,1,1) -- on remets la couleur par defaut pour la suite des appels

end

function love.keypressed(key)
  if key == "space" and balle.isGlue == true then
    balle.isGlue = false
  end
end

Votre premier jeu fonctionne =D

Si vous souhaitez améliorer le jeu, Il y a quelques pistes :

  • Mettre une image de fond
  • Ajouter des sons de bruitages lors des collisions
  • Mettre une musique
  • Garder le meilleur score en mémoire
  • Remplacer les briques, la balle et la raquette par des images
  • Augmenter la vitesse de la raquette
  • Augmenter la vitesse de la balle après chaque stage complété
  • Augmenter la valeur de vies des briques
  • Améliorer les collisions
  • etc.

Vous pouvez essayer de faire ceci, en vous aidant du wiki de love2d.


Pour ce premier jeu, j’ai volontairement simplifié pas mal de concepts qu’on reverra plus tard en profondeur dans les cours suivants.

Entraîner vous déjà avec le casse brique comme exercice.

Il faut que vous puissiez le refaire en vous aidant le moins possible.


Pour les niveaux intermédiaires, je vous propose une approche Orienté Objet à la page suivante.

Le Casse Brique version Orienté Object