En faisant peser sur ton joueur une menace continue venant d'un bord de l'écran, tu vas pouvoir ajouter de la tension à ton jeu. En variant la direction de la coulée de lave, il est aussi possible de condamner puis de rendre accessible certains passages de ton niveau.
Déclarer un symbole
Nous allons maintenant déclarer un nouveau type d'objet que tu vas pouvoir placer dans ton jeu.
Cet objet va nous permettre de déterminer la direction de la coulée de lave.
Dans cet exemple nous avons choisi le caractère +
.
Dans le script level.js
, trouve la variable LEVEL_CONFIG
et ajoutes-y le code ci-dessous, comme suit.
// défini ce à quoi correspond chaque symbole dans le niveau
const LEVEL_CONFIG = {
// taille en pixel de chaque case
width: 64,
height: 64,
// sol
"=": () => [
sprite("grass"),
area(),
solid(),
origin("bot")
],
// direction de la lave
"+": () => [
area(),
"camerapoint",
],
} ;
Placer les points de direction
Tu vas maintenant pouvoir choisir la direction de ta coulée de lave, mais pour cela il va d'abord te falloir comprendre comment ceux-ci fonctionnent.
- le premier point doit se trouver sur la même ligne ou colonne que ton joueur
- la position du point par rapport au joueur va déterminer le sens de la coulée
- si le joueur dépasse ce point, la coulée se dirige vers le point suivant
- le point suivant doit se trouver sur la même ligne ou colonne que le point précédent
- la position du point par rapport au point précédent va déterminer le sens de la coulée
- et ainsi de suite, jusqu'à ce qu'il n'y ait plus de point
level.js
, trouve le tableau LEVELS
et places des caractères +
là où tu le souhaites.
// plan du niveau
const LEVELS = [
[
" + " ,
" @ " ,
" = " ,
" = " ,
" = " ,
" = = " ,
" = " ,
" " ,
" = " ,
" " ,
" = " ,
" " ,
" =" ,
" " ,
" = " ,
" " ,
" = " ,
" = = " ,
" # = = + " ,
"=== = " ,
],
];
Tes points sont placés mais la coulée de lave n'est pas encore là.
Créer un nouveau composant
Pour que ta coulée de lave apparaisse, il va nous falloir créer un nouveau composant.
Rends-toi dans le script component.js
et ajoutes-y cette fonction.
function lava( speed = 160 , followB = false , looping = false ) {
const w = 240 ; // marge entre le joueur et la lave
const ha = 0.4 ; // amplitude de l'effet de chaleur
const hs = 0.6 ; // vitesse de l'effet
const hr = 10 ; // décalage entre les vagues de chaleur
const rd = 6 ; // nombre de vagues
const ra = 2 ; // amplitue de la rotation des vagues
const rr = 10 ; // décalage de la rotation des vagues
let currentCameraTarget = 0 ;
let cameraTargets = [] ;
let cameraDirections = [] ;
let heatbox = [] ;
let start = false ;
const hitbox = add( [
pos(0,0) ,
rect(0,0) ,
color(255,100,80) ,
area(),
origin("center"),
"danger",
] ) ;
return {
add(){
onKeyPress(() => {
start = true ;
})
},
load(){
let cp = get("camerapoint");
let pt = get("playerstart");
let st = new Vec2(0,0);
every( "start" , ( s ) => {
st = s.pos ;
});
this.pos = st ;
every( "camerapoint" , ( ) => {
let sd ;
let sdn ;
let b = false ;
for(let i = 0 ; i < cp.length ; i++){
let p = cp[i].pos ;
let d = this.distance( p , st );
if( ( !sd || d<sd ) && ( p.x == st.x || p.y == st.y ) ) {
sd = d ;
sdn = i ;
b = true
}
}
for(let i = 0 ; i < rd ; i++){
let lyr = ["foreground","background"];
heatbox[i] = add( [
pos(0,0) ,
rect(0,0) ,
color(255,100,80) ,
area(),
opacity(0.2),
rotate( wave( -ra , ra , i * rr ) ) ,
origin("center"),
layer(lyr[ i % lyr.length ])
] ) ;
}
if (b){
let np = cp[sdn].pos ;
let dx = np.x - st.x ;
let dy = np.y - st.y ;
let dir ;
if( Math.abs(dx) > Math.abs(dy) ){
if(dx<0) dir = new Vec2(-1, 0);
else dir = new Vec2( 1, 0);
}
else {
if(dy<0) dir = new Vec2( 0 , -1 );
else dir = new Vec2( 0 , 1 );
}
cameraTargets.push( new Vec2( np.x + dir.x , np.y + dir.y ) ) ;
cameraDirections.push( dir ) ;
st = np ;
cp.splice( sdn , 1 ) ;
}
});
},
update() {
if ( currentCameraTarget < cameraTargets.length ) {
let p = get("player")[0].pos ;
let d = cameraDirections[currentCameraTarget] ;
let t = cameraTargets[currentCameraTarget] ;
let x = this.pos.x ;
let y = this.pos.y ;
if (start){
if (d.x == 0) this.pos.x = p.x ;
else this.pos.x += d.x * speed * dt() ;
if (d.y == 0) this.pos.y = p.y ;
else this.pos.y += d.y * speed * dt() ;
if (followB){
if( d.x == 1 && x < p.x ) this.pos.x = p.x ;
if( d.x == -1 && x > p.x ) this.pos.x = p.x ;
if( d.y == 1 && y < p.y ) this.pos.y = p.y ;
if( d.y == -1 && y > p.y ) this.pos.y = p.y ;
}
if ( d.x < 0 && x <= t.x - w ) currentCameraTarget ++ ;
if ( d.x > 0 && x >= t.x + w ) currentCameraTarget ++ ;
if ( d.y < 0 && y <= t.y - w ) currentCameraTarget ++ ;
if ( d.y > 0 && y >= t.y + w ) currentCameraTarget ++ ;
if ( d.x < 0 && p.x <= t.x ) currentCameraTarget ++ ;
if ( d.x > 0 && p.x >= t.x ) currentCameraTarget ++ ;
if ( d.y < 0 && p.y <= t.y ) currentCameraTarget ++ ;
if ( d.y > 0 && p.y >= t.y ) currentCameraTarget ++ ;
}
hitbox.height = height() * 2 ;
hitbox.width = width() * 2 ;
hitbox.pos.x = x - ( width() + w ) * d.x ;
hitbox.pos.y = y - ( height() + w ) * d.y ;
for(let i = 0 ; i < heatbox.length ; i++){
let amp = (1 / heatbox.length * i + 1 );
let t = time() * hs + i * hr ;
heatbox[i].height = hitbox.height ;
heatbox[i].width = hitbox.width ;
heatbox[i].pos.x = hitbox.pos.x + wave(amp,amp+w,t) * d.x * ha ;
heatbox[i].pos.y = hitbox.pos.y + wave(amp,amp+w,t) * d.y * ha ;
}
}
else if (looping) currentCameraTarget = 0 ;
},
distance( e , t ){
const dx = Math.pow( e.x - t.x , 2 ) ;
const dy = Math.pow( e.y - t.y , 2 ) ;
return Math.sqrt( dx + dy ) ;
},
}
}
Ajouter le nouveau composant
Nous devons maintenant créer un nouvel objet dans ta scène puis y ajouter ce nouveau composant.
Dans le script game.js
, à l'intérieur de la scène game
, après la variable level
crée l'objet lavaflow
.
// ajoute le niveau
const level = addLevel( LEVELS[ CURRENT_LEVEL ] , LEVEL_CONFIG ) ;
// définition de la lave
const lavaflow = add( [
lava( 160 , false , false ) ,
] ) ;
Facultatif : Déplacer la caméra
Si tu le souhaites, il est aussi possible de déplacer la caméra du joueur, afin d'accentuer le sentiment d'urgence produit par la lave. Cela peut aussi permettre d'afficher davantage le reste du parcours.
Toujours dans le script game.js
, à l'intérieur de la scène game
, retrouve l'objet lavaflow
et modifie cette ligne.
// définition de la lave
const lavaflow = add( [
lava( 160 , false , false ) ,
lava( 160 , true , false ) ,
] ) ;
Enfin, dans le script game.js
, à l'intérieur de la scène game
, trouve la fonction l'objet onUpdate
et modifie cette ligne.
// est lu à chaque frame
onUpdate( () => {
// mouvement de la caméra
camPos( player.pos ) ;
camPos( lavaflow.pos ) ;
} ) ;