让我们看一下游戏的最终效果:
The video 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();
}
使蛇向前移动
有了蛇和食物后,下一步是处理蛇走路的逻辑。包括:
- 蛇是到达边界还是触摸其身体
- 当蛇碰到食物时,它的身体变得更长
- 在其他情况下,前进
/**
* 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。