XIV. Scrolling▲
Jusqu'à maintenant, nous avons travaillé avec des environnements en 640 par 480 (de la taille de notre fenêtre SDL).
Ce tutoriel va vous apprendre à vous déplacer à travers des environnements de n'importe quelle taille en utilisant le principe du scrolling (défilement).
XIV-1. Scrolling de la caméra▲
Quand on fait un jeu qui requiert du scrolling, la seule différence est qu'il nous faut ce qu'on appelle une caméra.
Vu qu'on ne peut pas afficher le niveau en entier à l'écran qui est trop petit, il nous suffit de prendre la partie du niveau qu'on veut afficher (généralement celle contenant notre élément actif).
Par exemple sur l'image suivante, la partie qu'on va afficher est entourée en rouge :
Il faut penser aussi que la caméra doit suivre notre point sur l'image si celui se met à bouger.
Dans cette partie du tutoriel, nous allons créer ce programme.
Dans la déclaration des variables, on va voir apparaître quelques nouveautés.
//Les attributs de l'écran (640 * 480)
const
int
SCREEN_WIDTH =
640
;
const
int
SCREEN_HEIGHT =
480
;
const
int
SCREEN_BPP =
32
;
//Le nombre de frame par seconde
const
int
FRAMES_PER_SECOND =
30
;
//Les dimensions du point (l'image qu'on va deplacer)
const
int
POINT_WIDTH =
20
;
const
int
POINT_HEIGHT =
20
;
//Vitesse de deplacement du point (en pixel par seconde)
const
int
POINT_VITESSE =
200
;
//Les dimensions du niveau
const
int
LEVEL_WIDTH =
1280
;
const
int
LEVEL_HEIGHT =
960
;
//Les surfaces
SDL_Surface *
point =
NULL
;
SDL_Surface *
background =
NULL
;
SDL_Surface *
screen =
NULL
;
//La structure d'événements que nous allons utiliser
SDL_Event event;
//La camera
SDL_Rect camera =
{
0
, 0
, SCREEN_WIDTH, SCREEN_HEIGHT }
;
Comme vous le voyez, on a définie les dimensions de notre niveau en plus de celles de la fenêtre SDL, celle-ci étant plus petite que le niveau.
On voit aussi apparaître la caméra qui est tout simplement un SDL_Rect car de forme rectangulaire.
On initialise cette caméra à la taille de notre fenêtre SDL car ce que l'on va afficher sera de la taille de notre fenêtre SDL.
Encore une fois, nous allons devoir revoir notre classe Point afin d'y ajouter la caméra :
class Point
{
private
:
//Les coordonnées x et y du point
int
x, y;
//La vitesse du point
int
xVel, yVel;
public
:
//Initialisation des variables
Point
(
);
//Recupere la touche pressee et ajuste la vitesse du point
void
handle_input
(
);
//Bouge le point
void
move
(
);
//Montre le point sur l'ecran
void
show
(
);
//Met la camera sur le point
void
set_camera
(
);
}
;
C'est la même chose qu'avant, sauf qu'on ajoute une fonction set_camera() pour centrer la caméra sur notre point.
Autre chose que l'on va retoucher légèrement est la fonction move() de notre Point.
En effet, on ne va plus tester les collisions avec les bords de notre fenêtre SDL et donc de l'écran mais avec les bords du niveau.
void
Point::move
(
)
{
//Bouge le point à gauche ou à droite
x +=
xVel;
//Si le point se rapproche trop des limites(gauche ou droite) de l'ecran
if
(
(
x <
0
) ||
(
x +
POINT_WIDTH >
LEVEL_WIDTH ) )
{
//On revient
x -=
xVel;
}
//Bouge le point en haut ou en bas
y +=
yVel;
//Si le point se rapproche trop des limites(haute ou basse) de l'ecran
if
(
(
y <
0
) ||
(
y +
POINT_HEIGHT >
LEVEL_HEIGHT ) )
{
//On revient
y -=
yVel;
}
}
Comme vous pouvez le voir, la différence par rapport à avant est minime.
Nous ne gardons donc plus notre point dans l'écran mais dans notre niveau.
Nous allons maintenant regarder la fonction set_camera().
void
Point::set_camera
(
)
{
//Centre la camera sur le point
camera.x =
(
x +
POINT_WIDTH /
2
) -
SCREEN_WIDTH /
2
;
camera.y =
(
y +
POINT_HEIGHT /
2
) -
SCREEN_HEIGHT /
2
;
Quand nous mettons en place la caméra, dans un premier temps nous la centrons autour du point (le point étant le centre de la caméra).
Cependant si nous ne faisons que ça, quand le point va se rapprocher des bords du niveau, on va voir apparaître du vide comme c'est le cas sur l'image ci-dessous :
Pour éviter cela, on va arrêter le mouvement de la caméra lorsque le point arrive vers les extrémités du niveau.
Cela aura pour conséquence de ne plus voir de vide et de voir le point continuer à bouger alors que la caméra s'est arrêtée.
//Garde la camera sur les bords
if
(
camera.x <
0
)
{
camera.x =
0
;
}
if
(
camera.y <
0
)
{
camera.y =
0
;
}
if
(
camera.x >
LEVEL_WIDTH -
camera.w )
{
camera.x =
LEVEL_WIDTH -
camera.w;
}
if
(
camera.y >
LEVEL_HEIGHT -
camera.h )
{
camera.y =
LEVEL_HEIGHT -
camera.h;
}
}
Si une partie de la caméra va en dehors du niveau, nous la remettons tout simplement dans le niveau, c'est le même principe de collision avec un objet statique vu dans le chapitre XI.
La fonction pour afficher le point va aussi changer un peu.
En effet, maintenant on va l'afficher sur l'écran relativement à la caméra.
void
Point::show
(
)
{
//Affiche le point
apply_surface
(
x -
camera.x, y -
camera.y, point, screen );
}
Dans notre boucle principale du main, voici comment ça se déroule :
//Tant que l'utilisateur n'a pas quitter
while
(
quit ==
false
)
{
//On demarre le timer fps
fps.start
(
);
//Tant qu'il y a un événement
while
(
SDL_PollEvent
(
&
event ) )
{
//On recupere l'evenement pour le point
monPoint.handle_input
(
);
//Si l'utilisateur a cliqué sur le X de la fenêtre
if
(
event.type ==
SDL_QUIT )
{
//On quitte the programme
quit =
true
;
}
}
//Bouge le point
monPoint.move
(
);
//Met la camera
monPoint.set_camera
(
);
//Affiche le fond
apply_surface
(
0
, 0
, background, screen, &
camera );
//Affiche le point sur l'écran
monPoint.show
(
);
On bouge le point, on met la caméra en place, on affiche la partie du fond dans la caméra puis on affiche le point.
Rien de bien sorcier.
Vous pouvez retrouver les sources du programme de cette partie du tutoriel ici :
Télécharger les sources du chapitre XIV-1 (854 ko)
XIV-2. Scrolling du background▲
Il peut arriver qu'on ait besoin d'un niveau de taille infinie, dans ce cas il serait impossible de passer le niveau comme précédemment.
Une solution est de faire défiler un fond en boucle.
Il peut aussi arriver que vous vouliez faire un jeu avec un niveau prédéfinit particulièrement long et que ce niveau avance tout seul, comme le célèbre vieux jeu R-Type.
Cette partie du tutoriel a pour but de créer un programme capable de faire un défilement du niveau.
Le défilement horizontal d'un niveau ressemble à quelque chose comme ça :
Il est bien sûr possible de faire un défilement vertical avec le même principe.
En réalité, le fond est blitté de multiples fois comme si une caméra avançait dessus.
Quand on arrive au bout du fond, on le remet au début, ce qui nous donne une impression d'infinie.
Pour débuter, il nous faut donc mettre le fond au départ :
//Les coordonnées du fond
int
bgX =
0
, bgY =
0
;
Vu que le fond bouge, nous devons garder en mémoire ses coordonnées.
Dans la boucle principale du main, on va bouger ce fond :
//Tant que l'utilisateur n'a pas quitter
while
(
quit ==
false
)
{
//On demarre le timer fps
fps.start
(
);
//Tant qu'il y a un événement
while
(
SDL_PollEvent
(
&
event ) )
{
//Si l'utilisateur a cliqué sur le X de la fenêtre
if
(
event.type ==
SDL_QUIT )
{
//On quitte the programme
quit =
true
;
}
}
//Defilement du fond
bgX -=
2
;
//Si le fond est allé trop loin
if
(
bgX <=
-
background->
w )
{
//On le remet à zero
bgX =
0
;
}
Après la récupération des événements, nous déplaçons le fond vers la gauche.
Ensuite nous vérifions si celui-ci est allé trop loin et nous le remettons au début le cas échéant.
Il nous reste à l'afficher :
//Affichage du fond
apply_surface
(
bgX, bgY, background, screen );
apply_surface
(
bgX +
background->
w, bgY, background, screen );
//Affcihage du point
apply_surface
(
310
, 230
, point, screen );
Nous affichons le fond sur l'écran placé avec ses coordonnées.
Pour mieux voir le rendu de ce défilement, nous ajoutons un point statique (je vous laisse le soin de le rendre dynamique).
Les sources de ce programme sont téléchargeable ici :
Télécharger les sources du chapitre XIV-2 (306 ko)
Sources et pdf▲
Remerciements▲
Je remercie Aspic pour sa correction orthographique.