J’ai décidé que l’objectif du jeu serait de collecter du minerai. Pour terminer un niveau, il faut apporter chaque tas de minerai au collecteur.

Ramasser du minerai

Dans un premier temps on s’inspire de ce qu’on a déjà fait avec les barils de fuel. On remplit un tableau avec des hash représentant des sprites de minerai et on les affiche :

  args.state.ores ||= [
    { x:1220, y: 282, w: 30, h: 27, path: 'sprites/gold.png', used: false },
    # ...
  ]

  args.outputs.sprites << args.state.ores

Lorsqu’on détecte une collision entre le personnage et un tas de minerai, celui-ci est considéré comme ramassé :

  args.state.ores.each do |o|
    if args.state.hero.intersect_rect?(o)
      o.used = true
    end
  end
  args.state.ores.reject!(&:used)

Apporter le minerai au collecteur

Maintenant on ajoute le collecteur, qui est simplement un endroit où le personnage va devoir déposer le minerai :

  args.state.collector ||= { x:0, y: 582, w: 80, h: 80, path: 'sprites/collector.png' }

  args.outputs.sprites << args.state.collector

Le perso peut transporter un seul tas de minerai à la fois.

  args.state.hero ||= {
    # ...
    ore: 0,
  }

On transforme en conséquence la détection de collision :

  args.state.ores.each do |o|
    if args.state.hero.ore == 0 && args.state.hero.intersect_rect?(o)
      o.used = true
      args.state.hero.ore = 1
      puts "I pick one!"
    end
  end
  args.state.ores.reject!(&:used)

Et on dépose un tas de minerai au collecteur.

  if args.state.hero.ore == 1 && args.state.hero.intersect_rect?(args.state.collector)
    args.state.hero.ore = 0
    puts "100 points!"
  end

J’ajoute une indication visuelle pour savoir quand le perso transporte du minerai en affichant du minerai en dessous du personnage. Je n’en suis pas fou, mais ça fonctionne pour l’instant.

  if args.state.hero.ore == 1
    args.outputs.sprites << {
      x: args.state.hero.x,
      y: args.state.hero.y,
      w: 30, h: 40, path: 'sprites/gold.png'
    }
  end
  args.outputs.sprites << args.state.hero

Première notion de niveau

On peut commencer à penser les niveaux du jeu. On crée une structure, qui pour l’instant contient un minimum d’informations : le nombre de minerai restant à collecter et si oui ou non le niveau est terminé.

  args.state.level ||= {
    remaining_ores: 5,
    completed: false,
  }

On met à jour ces infos quand le personnage dépose du minerai dans le collecteur.

  if args.state.hero.ore == 1 && args.state.hero.intersect_rect?(args.state.collector)
    args.state.hero.ore = 0
    args.state.level.remaining_ores -= 1
    args.state.level.completed = true if args.state.level.remaining_ores == 0
  end

Et finalement on indique quand le niveau est terminé :

  if args.state.level.completed
    args.outputs.labels << {
      x: 640,
      y: 360,
      size_px: 120,
      alignment_enum: 1,
      vertical_alignment_enum: 1,
      text: "Level Completed!",
      r: 255,
      g: 255,
      b: 255,
    }
  end

Références

  1. Vous trouverez le code de Jetpack Hero sur github
  2. Documentation de DragonRuby


/ / / / / / / / / /


Cet article fait partie d’une série :

  1. Jetpack Hero
  2. Partie II
  3. Une platforme, des collisions
  4. Première animation du personnage
  5. Ajouter des platformes
  6. Du carburant pour le jetpack
  7. Collecte de minerai
  8. Effets sonores
  9. Du rangement avec la classe Game
  10. Apparition des aliens
  11. Tir du personnage
  12. On dégomme de l’alien
  13. GAME OVER
  14. Les aliens bougent enfin