Ce chapitre est la troisième partie du tutoriel de programmation de notre jeu de type Tower Defense avec Three.JS.
Pour bien commencer, je vous suggère de débuter par la première partie de notre tutoriel :
Ce chapitre est également disponible au format vidéo !
Introduction
Dans ce nouveau chapitre, nous allons implémenter un système de Raycaster Three.JS afin de mettre en place des événements souris ou tactiles :
Événements souris et tactiles – Raycaster
Les variables globales
Commençons par créer quelques variables. Nous allons utiliser ces dernières pour implémenter un Raycaster
.
Nous utilisons le Raycaster pour sélectionner des éléments de l’univers 3D avec la souris ou un écran tactile.
Dans le fichier index.html
, créons les variables suivantes :
//Variables [...] // RAYCASTER var raycaster; var mouse = new THREE.Vector2(); var clickableObjs = new Array(); [...]
Commençons avec la variable raycaster
. Elle contiendra une instance de classe Raycaster
Three.JS, nous l’initialiserons dans la fonction init
.
La variable mouse
sera utilisée pour stocker la position du clic.
Pour finir, la structure Array
clickableObjs
stockera tous les éléments 3D de la scène éligibles à être ciblés par le Raycaster
.
Définir certains de nos objets 3D éligibles au ciblage
Commençons par le fichier map.js
, c’est dans la fonction loadMap
que nous chargeons dynamiquement la carte de jeu.
Dans notre scène, nous souhaitons pouvoir sélectionner les blocs de type 0
. Pour cela, ajoutons ces objets 3D à la liste clickableObjs
lors de leur création dans le switch - case 0
.
Il est également nécessaire de rajouter un paramètre dans la définition de loadMap
, pour que nous puissions y utiliser la variable clickableObjs
.
export function loadMap(mapdata, scene, clickableObjs) { [...] case 0: var tmpbloc = basic_cube.clone(); tmpbloc.position.set(posx, 0, posy); scene.add(tmpbloc); // This element is targetable by Raycaster clickableObjs.push(tmpbloc); break; [...]
Désormais, tous les objets 3D de ce type sont désormais éligibles à la sélection du Raycaster
.
Puis, modifions l’appel de loadMap
dans index.html
en conséquence :
loadMap(map0_data, scene, clickableObjs);
Créer un pointeur de souris 3D
Commençons par créer un curseur 3D pour pouvoir visualiser la position d’un clic dans notre carte de jeu.
Pour cela, dans index.html
, créons une variable globale cursor_cube
:
// Game objs var cursor_cube = undefined; // ThreeJS Mesh - RAYCASTER CURSOR
Puis, initialisons cette variable dans la fonction init
:
const cursor_material = new THREE.MeshLambertMaterial({ transparent : true , opacity : 0 , color : 0xc0392b}); const cursor_geometry = new THREE.BoxGeometry( 0.5, 4, 0.5 ); // height 4 cursor_cube = new THREE.Mesh( cursor_geometry, cursor_material ); scene.add(cursor_cube);
Facultatif – Il est également possible de modéliser un curseur 3D un peu plus réaliste. Pour cela, vous pouvez utiliser le tutoriel ci-dessous pour importer un modèle 3D dans votre application :
Implémenter le Raycaster Three.JS
Dans la fonction init
, initialisons notre variable raycaster
:
raycaster = new THREE.Raycaster();
Lorsque notre Raycaster
est prêt, poursuivons avec l’implémentation des événements JavaScript.
Les événements JavaScript
Commençons par créer deux fonction JavaScript, onMouseDown
et onMouseUp
:
function onMouseUp(event) { //code } function onMouseDown(event) { //code }
Puis, dans la fonction init
, connectons ces deux fonctions aux événements JavaScript pointerdown
et pointerup
:
// ---------------- EVENTS ---------------- document.addEventListener( 'pointerdown', onMouseDown, false ); document.addEventListener( 'pointerup', onMouseUp, false );
Ainsi, la fonction onMouseDown
sera appelée lorsque le clic de souris est pressé ou lorsque le doigt touche l’écran tactile, contrairement à la fonction onMouseUp
, appelée lors du relâchement de la pression du clic.
Commençons par le code de onMouseDown
, et capturons les coordonnées du clic dans notre variable mouse
:
function onMouseDown(event) { event.preventDefault(); mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1; mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1; }
Puis, utilisons notre Raycaster
pour détecter si des objets de la liste clickableObjs
sont ciblés :
function onMouseDown(event) { [...] // Checking if the mouse projection is targeting a valid block in the clickableObjs array raycaster.setFromCamera( mouse, camera ); var intersects = raycaster.intersectObjects( clickableObjs ); // get the list of targetable objects currently intersecting with raycaster }
Si au moins un élément de clickableObjs
est ciblé par la trajectoire du Raycaster, nous nous baserons sur le premier élément détecté pour y déplacer le pointeur 3D :
if ( intersects.length > 0 ) // If there is a match mouse/block (if the array is not empty) { var SelectedBloc = intersects[ 0 ].object; // we choose the first targetable element cursor_cube.position.set(SelectedBloc.position.x, SelectedBloc.position.y, SelectedBloc.position.z); cursor_cube.material.opacity = 0.5; cursor_cube.material.emissive.g = 0.5; }
Dans ce cas, définissons également l’opacité de notre pointeur sur 0.5
et donnons lui une couleur verte.
Mais, si aucun élément de la liste clickableObjs
est ciblé, nous cachons le pointeur :
else // no valid block is targeted { cursor_cube.material.opacity = 0; }
Nous avons terminé la fonction onMouseDown
!
Puis, dans le corps de la fonction onMouseUp
, réinitialisons la couleur de notre pointeur :
function onMouseUp(event) { cursor_cube.material.emissive.g = 0; }
Résultat final
Téléchargez le code final : Github.
Félicitations, vous êtes arrivés à la fin de cette troisième partie ! Nous sommes désormais capables de cibler certains éléments de notre carte de jeu grâce a un clic !
Ou, si vous avez opté pour l’option d’importer un curseur 3D depuis un fichier externe :
Dans la prochaine partie, nous programmerons la création dynamique d’objets ( de tours) dans notre scène grâce au Raycaster !
[…] Créer un jeu de Tower Defense avec Three.JS – Partie 3 Étiquettesdefensegamedevthree.jsthreejstowervideo […]