Tir du personnage (Jetpack Hero)
Le personnage doit pouvoir tirer au laser pour dégommer les aliens. Voyons comment gérer les entrées, ajouter du son, animer le tir, etc…
Un tir très simple pour commencer
Dans cette première version il est impossible de tirer plus d’une fois. Impossible aussi de tirer à gauche, le laser part toujours à droite. Bref, pas très utile, mais il faut bien commencer quelque part.
Je commence par ajouter l’état shooting
dans le hash hero
pour savoir si un
tir est en cours.
state.hero ||= {
# ...
shooting: false,
}
Il nous faut un hash pour conserver les sprites de laser, et il faut les afficher.
state.shots ||= []
outputs.sprites << state.shots
On déclenche le tir avec la touche ALT ou un bouton de la manette.
Sans la ligne if state.shots.empty?
un tir serait déclenché à chaque frame. Essayez pour voir le problème.
if inputs.keyboard.alt || inputs.controller_one.b
if state.shots.empty?
state.hero.shooting = true
audio[:laser] = { input: 'sounds/laser.wav' }
end
end
Si un tir à eu lieu, on ajoute un sprite dans le hash shots
. Ce sprite sera
déplacé de 5 pixels vers la droite à chaque frame.
def calc_shot
if state.hero.shooting
state.shots << {
x: state.hero.x,
y: state.hero.y + 20,
w: 24,
h: 10,
path: 'sprites/laser.png',
}
state.hero.shooting = false
end
state.shots.each do |shot|
shot.x += 5
end
end
Pouvoir tirer et re-tirer
On ajoute un état dead
à chaque tir, qui passe à true
quand le sprite
disparait de l’écran. Ça permet de supprimer les tirs hors jeu avec reject!
.
De cette manière on obtient un tir à la space invaders.
def calc_shot
if state.hero.shooting
state.shots << {
# ...
dead: false,
}
state.hero.shooting = false
end
state.shots.each do |shot|
shot.x += 5
shot.dead = true if shot.x > Grid.w
end
state.shots.reject!(&:dead)
end
Tirer à droite et à gauche
L’état hero.moving
nous permet de savoir si le perso bouge vers la droite ou la gauche,
mais ne nous apprend rien quand à la direction à laquelle il fait face
lorsqu’il ne bouge pas. On va ajouter hero.facing
pour toujours savoir où le
perso regarde, même quand il est à l’arrêt.
state.hero ||= {
# ...
moving: :none,
facing: :right,
# ...
}
def input
if inputs.left
state.hero.moving = :left
state.hero.facing = :left
elsif inputs.right
state.hero.moving = :right
state.hero.facing = :right
else
state.hero.moving = :none
end
end
Maintenant on peut tirer dans la direction du regard du perso, par l’intermédiaire de
speed
.
def calc_shot
if state.hero.shooting
state.shots << {
# ...
speed: state.hero.facing == :right ? LASER_SPEED : -LASER_SPEED,
}
state.hero.shooting = false
end
state.shots.each do |shot|
shot.x += shot.speed
shot.dead = true if shot.x > Grid.w || shot.x < 0
end
state.shots.reject!(&:dead)
end
Cadence de tir
Disons qu’on veut pouvoir tirer toutes les 1/2 secondes, donc toutes les 30 frames :
FIRE_RATE = 30 # Maximum is one shot every FIRE_RATE frames
On va se souvenir du moment du dernier tir :
state.hero ||= {
# ...
last_shot_at: 0,
}
On autorisera un tir seulement si le dernier a eu lieu il y a plus d’une demi seconde :
if inputs.keyboard.alt || inputs.controller_one.b
if state.hero.last_shot_at + FIRE_RATE < Kernel.tick_count
state.hero.shooting = true
audio[:laser] = { input: 'sounds/laser.wav' }
end
end
On met à jour le moment du tir :
def calc_shot
if state.hero.shooting
state.shots << {
# ...
}
state.hero.shooting = false
state.hero.last_shot_at = Kernel.tick_count
end
Animation
Pour finir, voici une animation toute simple du laser. Celui-ci est retourné verticallement toutes les 10 frames :
LASER_ANIMATION = 10
def calc_shot
if state.hero.shooting
state.shots << {
# ...
animation_counter: LASER_ANIMATION,
flip_vertically: false,
}
state.hero.shooting = false
state.hero.last_shot_at = Kernel.tick_count
end
state.shots.each do |shot|
shot.animation_counter -= 1
if shot.animation_counter == 0
shot.animation_counter = LASER_ANIMATION
shot.flip_vertically = !shot.flip_vertically
end
shot.x += shot.speed
shot.dead = true if shot.x > Grid.w || shot.x < 0
end
state.shots.reject!(&:dead)
end
Références
- Vous trouverez le code de Jetpack Hero sur github
- Documentation de DragonRuby
Cet article fait partie d’une série :
- Jetpack Hero
- Partie II
- Une platforme, des collisions
- Première animation du personnage
- Ajouter des platformes
- Du carburant pour le jetpack
- Collecte de minerai
- Effets sonores
- Du rangement avec la classe Game
- Apparition des aliens
- Tir du personnage
- On dégomme de l’alien
- GAME OVER
- Les aliens bougent enfin
Commentaires
Pas encore trouvé de solution simple et non-invasive pour avoir des commentaires sur le blog. En attendant vous pouvez laisser votre Commentaire sur mastodon@lkdjiin