Août 2015

Volume 30, numéro 8

Cet article a fait l'objet d'une traduction automatique.

Développement de jeux - Introduction à la 3D pour les jeux Web

Par Michael Oneppo | Août 2015

Ajout d'une troisième dimension à un jeu il apporte vraiment à la vie. Vous pouvez regarder autour de n'importe quel point de vue et voir sous tous les angles d'un objet ou une scène. Mais comment pouvez vous réellement retirer ceci dans les coulisses ? Dans cette série d'articles, je vais marcher à travers les étapes pour faire des jeux 3D et vous montrer comment les bibliothèques comme three.js peut vous aident à atteindre l'environnement riche et 3D devient si populaire sur le Web. Dans ce premier volet, je vais garder les choses simples et se concentrer sur la construction d'une version 3D du jeu Ping tout d'abord décrit dans « A Web Game in an Hour » (msdn.microsoft.com/magazine/dn913185).

L'Illusion de la 3D

Tout rendu graphique 3D a un surprenant tour dans son sac. Les humains ne peut pas vraiment voir en 3D dimensions — surtout sur un écran d'ordinateur. Ensemble de dessin 3D vise à générer, ou restituer, une description de 3D d'une scène sur une image 2D. Lorsque vous ajoutez une troisième dimension pour obtenir des scènes plus immersives et réalistes, vous devrez jeter quelques données pour obtenir une image d'un point de vue spécifique. Cette notion est appelée projection. C'est un élément essentiel de ce qui rend des graphismes 3D fonctionne, comme illustré dans la scène 3D base Figure 1.

scène 3D Simple
Figure 1 scène 3D Simple

Dans cette scène, l'axe Z s'éloigne vers le haut et vers l'arrière. Si je voulais réellement visualiser sur l'écran, je pouvais il suffit de glisser l'information Z de chaque objet comme un moyen simple et valide de scène de projet de la 3D, comme le montre Figure 2.

écrasé scène 3D
Figure 2 écrasé scène 3D

Comme vous pouvez le voir, ce n'est pas exactement de Halo. Pour le photoréalisme, une scène 3D nécessite trois choses : une projection caméra appropriée, la géométrie et l'ombrage. Je vais couvrir chacun de ces concepts que j'ai reconstruire le jeu Ping comme un duel de jeu en 3D.

démarrage

Tout d'abord, je vais mettre en place la bibliothèque three.js. Il s'agit d'une configuration assez rapide, comme presque tout ce que vous faites avec three.js arrive en JavaScript. Voici le code HTML, que vous aurez besoin :

<html>
  <head>
    <title>Ping!</title>
    <script src=
      "//cdnjs.cloudflare.com/ajax/libs/three.js/r69/three.min.js"></script>
    <script src="ping3d.js"></script>
  </head>
  <body>
  </body>
</html>

Dans le ping3d.js de fichier JavaScript, je vais pour configurer three.js pour restituer une scène simple. Tout d'abord, je dois initialiser three.js et ajoutez sa zone de dessin à la page :

var scene = new THREE.Scene();
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

La scène est exactement ce que cela ressemble — un objet qui décrit notre scène et tous les objets. Le moteur de rendu est aussi évidemment nommé. En fonction d'une scène, le moteur de rendu le retirera à l'écran. Cela doit ressembler à certains de la 2D dessin systèmes j'ai décrits dans les articles précédents, « A Web jeu in an Hour, » « Les Techniques de dessin 2D et bibliothèques pour les jeux Web » (msdn.microsoft.com/magazine/dn948109) et "Moteurs de jeu 2D pour le Web" (msdn.microsoft.com/magazine/dn973016). Maintenant, j'ai besoin ajouter certains éléments à l'écran.

Geometry

Presque tous les graphismes 3D sont construites en polygones. Des surfaces courbes même comme une balle sont approximées à facettes triangulaires de rapprocher sa surface. Une fois assemblé, ces triangles sont appelés un maillage. Voici comment ajouter le ballon à la scène :

var geometry = new THREE.SphereGeometry(10);
var material = new THREE.BasicMaterial({color: 0xFF0000});
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

Ce code va créer un grand nombre de triangles représentant une sphère (la variable « géométrie »), un simple matériau rouge vif (le "contenu") et un objet maillé (la "maille"). Puis il va ajouter la maille à la scène.

Le triangle est le bloc de construction fondamental des graphismes en 3D. Pourquoi ? Je vais étudier cela plus loin dans le prochain article de cette série, mais les deux raisons principales sont les lignes droites qui forment un triangle sont faciles à travailler et vous ne pouvez pas casser un triangle sur une surface plane plus basique. L'unité de traitement graphique (GPU) sur votre ordinateur ou votre téléphone a consacré le matériel qui peut convertir rapidement des formes avec des lignes droites en pixels. Il s'agit d'une bonne partie de ce qui rend les graphiques 3D de haute qualité possible.

Modélisation

Je peux passer n'importe quelle géométrie dans les trois. Mesh, constructeur. Cela inclut la géométrie générée pour faire des formes personnalisées ou même les données depuis les fichiers. Pour le jeu de Ping, je voudrais avoir des modèles 3D de chacun des joueurs. Donc, j'ai pris la liberté de création de géométrie dans un programme de modélisation 3D pour cet exercice. Il est étonnamment facile à utiliser le modèle au lieu d'une sphère, comme three.js fournit un outil de chargement dans ce but :

var jsonLoader = new THREE.JSONLoader();
jsonLoader.load('tank1.json', function (geometry) {
  var material = new THREE.BasicMaterial({color: 0xFF0000});
  var mesh = new THREE.Mesh(geometry, material);
  scene.add(mesh);
});

Caméra

La caméra représente le point de vue de la scène. Il stocke la position et l'angle de la visionneuse dans le jeu. Plus important encore, la caméra représente comment la scène s'aplatit, comme décrit au début de cet article.

Dans mon exemple, la caméra est positionnée vers le bas et vers la droite. L'image finale est apparu comme le point de vue de cette direction. Toutefois, à l'aide de cette méthode de projection, n'importe quelle distance sont les objets, ils resteront la même taille dans l'image finale. C'est ce qu'on appelle une projection orthographique. Ceci est souvent utile pour les jeux avec des angles de vision non réaliste comme les jeux de simulation de ville. Ce que je veux atteindre est de fabriquer des objets apparaissent plus petits qu'ils reculent dans le lointain.

Entrez la projection en perspective : Projection de perspective s'imagine le champ de vision d'une caméra comme une pyramide qui s'étend de la lentille. Lorsque des postes sont mappées à l'écran, ils sont calculées en fonction sur leurs distances relatives aux côtés de la pyramide. En utilisant ce modèle, que les objets reculent au loin, ils semblent rétrécir comme dans la vraie vie.

Heureusement, vous n'avez pas besoin de faire ce mappage vous-même car three.js le fait pour vous et fournit un objet qui représente la caméra dans la scène (et ajout d'un autre est simple) :

var camera = new THREE.PerspectiveCamera(
  75, window.innerWidth/window.innerHeight, 0.1, 1000 );

Le premier argument est le champ de vision, ce qui indique combien d'une distance angulaire prise horizontale. Le deuxième argument est le rapport entre la largeur de l'écran à la hauteur, dont vous avez besoin pour s'assurer que les choses ne sont pas écrasés parce que l'écran n'est pas carré. Les finales deux paramètres définissent la distance plus proche et le plus éloignée à montrer. Quoi que ce soit plus près ou plus loin que ces valeurs n'est pas dessiné. Maintenant je suis au point où je peux en tirer réellement la scène. Nous allons déplacer la caméra arrière un peu pour voir toute la scène et de commencer le dessin :

camera.position.z = 50;
renderer.render(scene, camera);

Matières et lumières

Ensuite, je vais placer le ballon dans l'arène dans laquelle il rebondira :

var room = new THREE.BoxGeometry( 50, 30, 100 );
var material = new THREE.MeshPhongMaterial({
    side:  THREE.BackSide,
    map: THREE.ImageUtils.loadTexture('arena.png')
});
var model = new THREE.Mesh(room, material);
model.position.y = 15;
scene.add(model);

J'ai fais quelque chose de différent que simplement faire de géométrie de la boîte. Je fais aussi un matériau. Un matériau est une définition de la façon dont quelque chose devrait refléter la lumière dans une scène. Cette opération génère son apparence générale. Dans ce cas, j'ai fais un matériau Phong, qui est une bonne valeur par défaut pour les objets brillants. Je suis également ajouter une texture à la boîte, qui est simple à three.js en utilisant la fonction loadTexture.

Un autre aspect remarquable de ce code est la ligne qui se lit : côté : TROIS. Face arrière. Cela indique à three.js dessiner que les côtés intérieures des surfaces boîte, plutôt que les côtés extérieures. Cela donne place à la balle de rebondir, au lieu d'avoir une boîte solide flottant dans l'espace.

Si j'étais maintenant dessiner la scène, la scène ne serait pas visible. Il attire juste noir. C'est parce que les matériaux définissent comment lumière reflète sur les objets, et je n'ai pas encore de lumière dans la scène. Three.js simplifie l'ajout de lumière à une scène, comme illustré ici :

this.lights = [];
this.lights[0] = new THREE.PointLight( 0x888888, 1, 300 );
this.lights[0].position.set( 0, 10, 40 );
scene.add( this.lights[0] );
this.lights[1] = new THREE.PointLight( 0x888888, 1, 300 );
this.lights[1].position.set( 0, 20, -40 );
scene.add( this.lights[1] );

Maintenant si je dessine la scène, la scène restitue correctement. Pour apporter une meilleure vue, je vais définir la position de la caméra à regarder du côté de l'arène avant d'exécuter le code :

camera.up.copy(new THREE.Vector3(0,1,0));
camera.position.copy(new THREE.Vector3(0,17, -80));
camera.lookAt(new THREE.Vector3(0,0,40));

La première ligne définit la variable haut qui indique simplement la caméra qui est le haut. La fonction de lookAt fait exactement ce que cela puisse paraître, il pointe la caméra à la position spécifiée.

Faire un 3D jeu

Maintenant que le jeu a été déplacée en trois dimensions, rendant le reste devrait être assez facile. Cependant, ce jeu va finir vers le haut un peu plus documentée que les implémentations précédentes puisqu'elle est composée de la 3D au lieu des objets 2D. Donc, je te casse le code dans des fichiers séparés pour rendre le code PLU plus facile à manipuler.

Je vais aussi passer JavaScript styles pour la définition d'objet au modèle constructeur plus traditionnel. Pour illustrer cela, j'ai enveloppé la boîte de l'arène et s'allume en un objet et que placés dans un seul fichier, comme dans Figure 3.

Figure 3 l'objet Arena

function Arena(scene) {
  var room = new THREE.BoxGeometry( 50, 30, 100 );
  var material = new THREE.MeshPhongMaterial({
    side:  THREE.BackSide,
    map: THREE.ImageUtils.loadTexture('arena.png')
  });
  var model = new THREE.Mesh(room, material);
  model.position.y = 15;
  scene.add(model);
  this.lights = [];
  this.lights[0]= new THREE.PointLight( 0x888888, 1, 300 );
  this.lights[0].position.set( 0, 10, 40 );
  scene.add( this.lights[0] );
  this.lights[1]= new THREE.PointLight( 0x888888, 1, 300 );
  this.lights[1].position.set( 0, 20, -40 );
  scene.add( this.lights[1] );
}

Si je veux créer une arène, je peux créer un nouvel objet à l'aide de cette fonction de constructeur :

var arena = new Arena(scene);

Ensuite, je vais faire un objet sphérique qui peut rebondir autour de l'arène. Je sais comment faire une boule rouge dans three.js, donc je vais encapsuler ce code dans un objet, aussi bien :

function Ball(scene) {
  var mesh = new THREE.SphereGeometry(1.5, 10, 10);
  var material = new THREE.MeshPhongMaterial({
    color: 0xff0000,
    specular: 0x333333
  });
  var _model = new THREE.Mesh(mesh, material);
  _model.position.y = 10;
  scene.add(_model);
}

Maintenant, je vais définir la base physique de rebondir le ballon par l'ajout d'une fonction à l'objet de la balle, comme le montre Figure 4.

Figure 4 de l'objet balle mise à jour de la fonction

// Create a private class variable and set it to some initial value.
var _velocity = new THREE.Vector3(40,0,40);
this.update = function(t) {
  // Apply a little gravity to the ball.
  _velocity.y -= 25 * t;
  // Move the ball according to its velocity
  var offset = _velocity.clone()
    .multiplyScalar(t);
  _model.position.add(offset);
  // Now bounce it off the walls and the floor.
  // Ignore the ends of the arena.
  if (_model.position.y - 1.5 <= 0) {
    _model.position.y = 1.5;
    _velocity.y *= -1;
  }
  if (_model.position.x - 1.5 <= -25) {
    _model.position.x = -23.5;
    _velocity.x *= -1;
  }
  if (_model.position.x + 1.5 >= 25) {
    _model.position.x = 23.5;
    _velocity.x *= -1;
  }
}

Three.js nécessite que vous restituez la scène chaque fois à l'aide de requestAnimationFrame. Cela devrait être un motif familier :

var ball = new Ball(scene);
var Arena = new Arena(scene);
var render = function (time) {
  var t = (time - lastTime) / 1000.0;
  lastTime = time;
  ball.update(t);
  renderer.render(scene, camera);
  requestAnimationFrame( render );
}
requestAnimationFrame(render);

Restez connecté

Maintenant, j'ai une arène de lumières, une caméra bien placée et une balle qui rebondit autour de la scène. C'est tout ce que je vais couvrir dans cet article. Dans le prochain épisode, je vais vous expliquer comment 3D projection des œuvres de laisser vous visez avec la souris. Je vais aussi expliquer plus sur les textures et faire des animations fluides, en utilisant une bibliothèque puissante appelée tween.js. Dans le dernier de ces trois articles, je vais regarder sous le capot des three.js et voir comment il est réellement dessiner des graphismes de haute fidélité.


Michael Oneppo est technicien créatif et responsable de l'ancien programme chez Microsoft dans l'équipe de Direct3D. Ses efforts récents incluent le travail comme directeur technique à la technologie sans but lucratif de bibliothèque pour tous et d'explorer une maîtrise à l'Université de New York Interactive Telecommunications Program.

Merci aux experts techniques suivants d'avoir relu cet article : Mohamed Ameen Ibrahim