如何使用JavaScript创建3D蛇游戏(附加的源代码和游戏链接)
#javascript #教程 #gamedev #webgl

让我们看一下游戏的最终效果:
The video of the game

The snapshoot of the game

现在让我们谈谈如何使用JavaScript实现它。
该游戏是使用HT for Web进行的,大约有100行代码。

初始化场景

首先,让我们做一些初始化工作,包括初始化3D场景,设置地面网格以及启用事件监视等。主代码和评论如下:

  w = 40; // the grid gap
  m = 20; // the count of rows/columns of grid
  d = w * m / 2;
  food = null;            
  dm = new ht.DataModel(); // create one data model, which saves all the  grid, snake and food
  g3d = new ht.graph3d.Graph3dView(dm); // initialize one 3d scene  
  // config the grid on ground             
  g3d.setGridVisible(true);
  g3d.setGridColor('#29B098');
  g3d.setGridSize(m);
  g3d.setGridGap(w);    

  // add the 3d scene to body
  view = g3d.getView();            
  view.className = 'main';
  document.body.appendChild(view);   

  // monitor the resize event and mouse click event
  window.addEventListener('resize', function (e) {  g3d.invalidate(); }, false);                                                                                            
  g3d.sm().setSelectionMode('none');
  view.addEventListener(ht.Default.isTouchable ? 'touchstart' : 'mousedown', function(e){                
      if(isRunning){
          var p = g3d.getHitPosition(e); // get the position in scene when mousedown
          // calculate the move direction with the click position 
          if(Math.abs(p[0]) < d && Math.abs(p[2]) < d){
              if(direction === 'up' || direction === 'down'){
                  direction = p[0] > snake[0].p3()[0] ? 'right' : 'left';                       
              }
              else if(direction === 'left' || direction === 'right'){
                  direction = p[2] > snake[0].p3()[2] ? 'down' : 'up';                                             
              }                        
          }
      }else if(ht.Default.isDoubleClick(e)){
          start(); // double click the scene to start the game
      }                
  }, false);                        
  start();            
  // the snake move forward every 200ms
  setInterval(function(){ if(isRunning){ isRunning = next(); } }, 200);

创建食物

每当腹泻蛇吃一块食物时,它的身体就会长得更长。在这一点上,需要创建和随机创建新食物,并将其放置在新的位置。创建食物时,其位置不应与先前的位置一致,也不应与当前的蛇体重复。

/**
 * Create the food and place it in a random position
 * The food should not dup with snake or last food
 *
 */
function createFood(){
  var x = getRandom(), y = getRandom();
  // skip the snake body and last food
  while(touchFood(x, y) || touchSnake(x, y)){ x = getRandom(); y = getRandom(); }
  if(food) dm.remove(food);            
  food = createNode(x, y); 
  food.s({'shape3d': 'sphere',  'shape3d.color': 'red'});
}        
/**
 * whether the given position (x, y) is dup with the snake body
 *
 * @param {*} x
 * @param {*} y
 * @return {*} 
 */
function touchSnake(x, y){
  for(var i=0; i<snake.length; i++){                
      if(snake[i].a('x') === x && snake[i].a('y') === y){ return true; }
  }
  return false;
}        
/**
 * whether the given position (x, y) is dup with the food
 *
 * @param {*} x
 * @param {*} y
 * @return {*} 
 */
function touchFood(x, y){
  return food && food.a('x') === x && food.a('y') === y;
}      

创建蛇

在第一步中,我们设置了网格大小和间隙。这样,确定了整个网格的长度和宽度以及蛇的每个块的大小。在此步骤中,我们在网格中添加边界,然后生成蛇。

/**
 * clear the scene, create the snake and wall
 *
 */
function start(){
  dm.clear(); snake = []; score = 0; direction = 'up'; isRunning = true;
  // create wall
  shape = new ht.Shape();
  shape.setPoints(new ht.List([
      {x: -d, y: d},
      {x: d, y: d},
      {x: d, y: -d},
      {x: -d, y: -d},
      {x: -d, y: d}
  ]));
  shape.setThickness(4);
  shape.setTall(w);
  shape.setElevation(w/2);
  shape.s({'all.color': 'rgba(20, 120, 120, 0.5)', 'all.transparent': true, 'all.reverse.cull': true});

  dm.add(shape);                 
  // create the snake       
  for(var i=0; i<m/2; i++) { snake.push(createNode(m/2 + i, m/2)); }            
  createFood();                        
}        

使蛇向前移动

有了蛇和食物后,下一步是处理蛇走路的逻辑。包括:

  1. 蛇是到达边界还是触摸其身体
  2. 当蛇碰到食物时,它的身体变得更长
  3. 在其他情况下,前进
/**
 * calculate nest position based on direction. and check:
 * 1. whether the snake has reached the border or touched its body
 * 2. when the snake touched the food, its body gets longer
 * 3. in other cases, move forward
 *
 * @return {*} 
 */
function next(){
  var node = snake[0], x = node.a('x'), y = node.a('y');
  if(direction === 'up') y--;
  if(direction === 'down') y++;       
  if(direction === 'left') x--;
  if(direction === 'right') x++;
  if(x < 0 || x >= m || y < 0 || y >= m || touchSnake(x, y)){ return false; }                        
  if(touchFood(x, y)){
      score++;                
      snake.splice(0, 0, createNode(x, y));                
      createFood();
  }else{
      snake.splice(0, 0, createNode(x, y));
      dm.remove(snake.pop());                
  }
  return true;
}

此时,整个蛇游戏都完成了。很简单,对吧?双击场景以开始游戏或单击场景以更改蛇运动的方向。

您也可以直接单击下面的链接尝试游戏:
3D Gluttonous Snake

要获取源代码,只需打开游戏链接,然后按F12。