当前位置:嗨网首页>书籍在线阅读

18-简单区块移动逻辑概述

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

9.3.9 简单区块移动逻辑概述

微型坦克迷宫使用了简单的区块到区块的移动方式,并使用了“区块中心”的逻辑。这种逻辑的计算基础是游戏角色总是位于区块的中心。游戏角色区块的原始位置是左上角。因此,当游戏角色的x、y坐标等于目标区块的x、y坐标时,可以简单地认为游戏角色位于区块的中心。

当用户按下移动键时(上、下、左、右键),必须首先检查玩家是否正在向游戏区域上的一个“合法”区块移动。在微型坦克迷宫中,所有的区块都是合法的。唯一的非法移动是移动到游戏板的边界之外。所以,如果玩家要向上、下、左、右移动,在gameState WaitForPlayerMove()函数中,首先要根据按键检查该方向上的区块。下面的判断语句用于检测用户按下的方向键。

if (keyPressList[38]==true){
    //向上
    if (checkBounds(-1,0, player)){
    setPlayerDestination();
    }
  }else if (keyPressList[37]==true){
    //向左
    if (checkBounds(0,-1, player)){
    setPlayerDestination();
    }
  }else if (keyPressList[39]==true){
    //向右
    if (checkBounds(0,1, player)){
    setPlayerDestination();
    }
  }else if (keyPressList[40]==true){
    //向下
    if (checkBounds(1,0, player)){
    setPlayerDestination();
    }
  }

请注意,checkBounds函数使用一个行增量和一个列增量进行检测。重要的是,此处没有使用与访问屏幕像素相同的方式访问区块。playField数组中的区块通过先垂直(行)后水平(列)的地址进行访问(使用[行][列],而不是[列][行])。这是因为,一个简单的数组由一组行元素组成。每一行有15列。因此,不能使用[水平][垂直]的方式访问playfield中的区块。相反地,使用[行][列]的语法方式访问数据,不仅简单而且高效优雅。

在checkBounds()函数的参数中,首先是行的增量,之后是列的增量,最后是待测对象的实例。如果这是一个合法的移动,checkBounds()函数会分别将 nextRow 和 nextCol属性设置为row+rowInc和col+colInc。

function checkBounds(rowInc, colInc, object){
  object.nextRow = object.row+rowInc;
  object.nextCol = object.col+colInc;
  if (object.nextCol >=0 && object.nextCol<15 &&
  object.nextRow>=0 && object.nextRow<15){
   object.dx = colInc;
   object.dy = rowInc;
   if (colInc==1){
   object.rotation = 90;
   }else if (colInc==-1){
   object.rotation = 270;
   }else if (rowInc==-1){
   object.rotation = 0;
   }else if (rowInc==1){
   object.rotation = 180;
   }
   return(true);
  }else{
   object.nextRow = object.row;
   object.nextCol = object.col;
   return(false);
  }
}

如果移动合法,分别将dx(x的变化量)和dy(y的变化量)的值设置为colInc和rowInc。

接下来,调用animatePlayer()函数。这个函数的工作是将player对象移动到新的位置,并在这个过程中播放动画。以下是animatePlayer()函数中的部分代码。

player.x += player.dx*player.speed;
player.currentTile++; if (player.currentTile==playerTiles.length){
  player.currentTile = 0;
}
renderPlayField();
if (player.x==player.destinationX && player.y==player.destinationY){
  switchGameState(GAME_STATE_EVALUATE_PLAYER_MOVE);
}

首先,player对象的x、y坐标将增加player.speed * player.dx(或dy)。因为区块大小是32,所以必须使用一个可以整除32的速度值。例如,1、2、4、8、16和32都是合法的值。

这个函数还会在每个游戏循环中访问playerTiles数组。这样可以渲染出坦克履带移动的效果,平滑地从一个区块移动到下一个区块。

接下来,本书将带领读者深入了解如何渲染游戏区域。