<!DOCTYPE html>
<html>
<meta charset="utf-8" />
<script type="text/javascript" src="three.js"></script>
<body onload="init()">
<canvas id="mainCanvas" width="800px" height="600px"></canvas><br><br>
P开始暂停游戏<br><br>
W S A D 对应上下左右旋转地图<br><br>
箭头 上 下 左 右 对应蛇上下左右的转向
<script>
function init(){
function $(id){
return document.getElementById(id);
}
//获取一个0~X的随机数,包括0不包括X
function getInt(x){
var i = Math.floor(Math.random()*x);
return i;
}
//创建一个反光材质的方块,参数为长宽高和颜色
function createLambertCube(l,w,h,colo){
return new THREE.Mesh(
//形状 立方体
new THREE.CubeGeometry(l,w,h),
//材质 反光
new THREE.MeshLambertMaterial({color:colo})
);
}
//计算方块绕原点旋转时的瞬时位置
function Rotate(Source,Angle){
var A,R;
A = Math.atan2(Source.Y,Source.X)
A += Angle;
R = Math.sqrt(Source.X * Source.X + Source.Y * Source.Y);
return {
X : Math.cos(A) * R,
Y : Math.sin(A) * R
}
}
//方块自转(Y轴)的瞬时状态,du的正负控制两种方向旋转
function rotationCubeByY(obj,du){
obj.rotation.y=(obj.rotation.y-du)%(Math.PI*2);
}
//方块绕Y轴旋转的瞬时状态
function rotationFoodByY(obj,du){
var rot=Rotate({
X:obj.position.x,Y:obj.position.z
},du);
obj.position.x=rot.X;obj.position.z=rot.Y;
obj.rotation.y=(obj.rotation.y-du)%(Math.PI*2);
}
//蛇身绕Y轴旋转的瞬时状态
function rotationSnakeByY(obj,du){
for(var i=0;i<obj.length;i++){
var rot=Rotate({
X:obj[i].body.position.x,
Y:obj[i].body.position.z
},du);
obj[i].body.position.x=rot.X;
obj[i].body.position.z=rot.Y;
obj[i].body.rotation.y=(obj[i].body.rotation.y-du)%(Math.PI*2);
}
}
//方块自转(X轴)的瞬时状态
function rotationCubeByX(obj,du){
obj.rotation.x=(obj.rotation.x-du)%(Math.PI*2);
}
//方块绕X轴旋转的瞬时状态
function rotationFoodByX(obj,du){
var rot=Rotate({
X:obj.position.y,Y:obj.position.z
},-du);
obj.position.y=rot.X;
obj.position.z=rot.Y;
obj.rotation.x=(obj.rotation.x-du)%(Math.PI*2);
}
//蛇身绕X轴旋转的瞬时状态
function rotationSnakeByX(obj,du){
for(var i=0;i<obj.length;i++){
var rot=Rotate({
X:obj[i].body.position.y,
Y:obj[i].body.position.z
},-du);
obj[i].body.position.y=rot.X;
obj[i].body.position.z=rot.Y;
obj[i].body.rotation.x=(obj[i].body.rotation.x-du)%(Math.PI*2);
}
}
//纠正旋转过程中的位移偏差
function correcyCubeRotationY(obj){
obj.rotation.y=0;
//不保留小数位
obj.position.x=parseInt(obj.position.x.toFixed(0));
obj.position.z=parseInt(obj.position.z.toFixed(0));
}
//纠正旋转过程中的位移偏差
function correcySnakeRotationY(obj){
for(var i=0;i<obj.length;i++){
obj[i].body.position.x=parseInt(obj[i].body.position.x.toFixed(0));
obj[i].body.position.z=parseInt(obj[i].body.position.z.toFixed(0));
obj[i].body.rotation.y=0;
}
}
//纠正旋转过程中的位移偏差
function correcyCubeRotationX(obj){
obj.rotation.x=0;
obj.position.y=parseInt(obj.position.y.toFixed(0));
obj.position.z=parseInt(obj.position.z.toFixed(0));
}
//纠正旋转过程中的位移偏差
function correcySnakeRotationX(obj){
for(var i=0;i<obj.length;i++){
obj[i].body.position.y=parseInt(obj[i].body.position.y.toFixed(0));
obj[i].body.position.z=parseInt(obj[i].body.position.z.toFixed(0));
obj[i].body.rotation.x=0%(Math.PI*2);
}
}
//纠正旋转过程中的自转角度的偏差
function rotationAll(xx,du,obj1,obj2,obj3){
if(xx=="x"){
rotationCubeByX(obj1,du);
rotationFoodByX(obj2,du);
rotationSnakeByX(obj3,du);
}else if(xx=="y"){
rotationCubeByY(obj1,du);
rotationFoodByY(obj2,du);
rotationSnakeByY(obj3,du);
}
}
//纠正旋转过程中的位移偏差
function correcyrotationAll(xx,obj1,obj2,obj3){
if(xx=="y"){
correcyCubeRotationY(obj1);
correcyCubeRotationY(obj2);
correcySnakeRotationY(obj3);
}else if(xx=="x"){
correcyCubeRotationX(obj1);
correcyCubeRotationX(obj2);
correcySnakeRotationX(obj3);
}
}
//地图转向过程中的自转角度的偏差
function correcyTurn(tow){
if(tow==65 || tow==68){
if(lastkey==87 || lastkey==83){
cube.rotation.x=0;
food.rotation.x=0;
}
if((lastkey==68 && tow==65) || (lastkey==65 && tow==68)){
cube.rotation.y=-cube.rotation.y;
food.rotation.y=-food.rotation.y;
}
}else if(tow==83 || tow==87){
if(lastkey==65 || lastkey==68){
cube.rotation.y=0;
food.rotation.x=0;
}
if((lastkey==83 && tow==87) || (lastkey==87 && tow==83)){
cube.rotation.y=-cube.rotation.y;
food.rotation.x=-food.rotation.x;
}
}
lastkey=tow;
}
//判断是否为食物
function isFood(x,y,z){
if( x==food.position.x &&
y==food.position.y &&
z==food.position.z){
scene.remove(food);
snake.splice(0,0,{body:createLambertCube(1,1,1,0x4F9D9D)}
);
scene.add(snake[0].body);
cooking();
}
else
return false;
}
//制作一个食物
function cooking(){
food.position.x=getInt(8);
food.position.y=getInt(8);
food.position.z=getInt(8);
for(var i=0;i<snake.length;i++)
if( food.position.x==snake[i].body.position.x &&
food.position.y==snake[i].body.position.y &&
food.position.z==snake[i].body.position.z){
i=-1;
food.position.x=getInt(8);
food.position.y=getInt(8);
food.position.z=getInt(8);
}
scene.add(food);
}
//更新蛇身位置数据,蛇头不变
function updateSnake(){
for(var i=0;i<snake.length-1;i++){
snake[i].body.position.x=snake[i+1].body.position.x;
snake[i].body.position.y=snake[i+1].body.position.y;
snake[i].body.position.z=snake[i+1].body.position.z;
}
}
//获取蛇当前前行的方向,用蛇头减去蛇脖子
function getToward(){
var toward="";
if(snake[snake.length-1].body.position.x-
snake[snake.length-2].body.position.x>0)
toward="+x";
else if(snake[snake.length-1].body.position.x-
snake[snake.length-2].body.position.x<0)
toward="-x";
else if(snake[snake.length-1].body.position.y-
snake[snake.length-2].body.position.y>0)
toward="+y";
else if(snake[snake.length-1].body.position.y-
snake[snake.length-2].body.position.y<0)
toward="-y";
else if(snake[snake.length-1].body.position.z-
snake[snake.length-2].body.position.z>0)
toward="+z";
else if(snake[snake.length-1].body.position.z-
snake[snake.length-2].body.position.z<0)
toward="-z";
return toward;
}
//创建渲染器并绑定画布
var renderer=new THREE.WebGLRenderer({
canvas:document.getElementById("mainCanvas")
});
//渲染器初始化
renderer.setClearColor(0x666666);
//创建场景
var scene=new THREE.Scene();
//创建照相机并绑定画布
var camera=new THREE.PerspectiveCamera(65,$("mainCanvas").width/$("mainCanvas").height,1,100);
//照相机位置
camera.position.set(10,9,20);
//照相机观测方向
camera.lookAt(new THREE.Vector3(0,0,0));
//将照相机添加至场景中
scene.add(camera);
//创建地图
var cube=new THREE.Mesh(
new THREE.CubeGeometry(15,15,15),
new THREE.MeshBasicMaterial({color:0x999999,wireframe:true})
);
//添加地图
scene.add(cube);
//定义食物
var food=createLambertCube(1,1,1,0x53FF53);
//定义蛇
var snake=[