<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>三维消除箱子游戏</title>
<style>
body {
margin: 0;
padding: 0;
background-color: #eee;
color: #333;
font-family: helvetica;
}
canvas {
position: absolute;
}
.hud {
position: absolute;
margin-left: 1em;
}
.hit {
font-weight: bold;
color: red;
}
#xiayiguan{
position:absolute;
left:1000px;
top:500px;
background-color: #4CAF50;
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
}
#jiansu{
position:absolute;
left:900px;
top:500px;
background-color: rgb(181, 197, 39);
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
}
</style>
</head>
<body>
<div class="hud">
<h1 id="level"></h1>
<p>点击箱子将其消除</p>
<p id="score"></p>
</div>
<div id="webgl-container"></div>
<button id="xiayiguan" onclick="xiayiguan()">下一关</button>
<button id="jiansu" onclick="jiansu()">减速</button>
<script src="three.min.js"></script>
<script src="game.js"></script>
</body>
</html>
//1,变量定义
var scene;
var cube;
var camera;
var renderer;
var clock;//计时器
var holder;//容器
var intersects;//交互变量
var particles=[];//例子数组
var level=1;
var totalLevels=4;
var score=0;
var totalTargets=1;//第一局的目标数
var speed=0.01;
var complete=false;//是否通关
var comments=["简单","中等","困难","疯狂"];
var clicktime=0;
var myLevel=document.getElementById("level");
var myScore=document.getElementById("score");
var mybutton=document.getElementById("xiayiguan");
var now = new Date();
var starttime = now.getMinutes();
//2,初始化
var raycaster=new THREE.Raycaster();//Raycaster类用于2D鼠标在3D场景中拾取对象
var mouse=new THREE.Vector2();
//创建场景
function myScene()
{
scene=new THREE.Scene();
var light=new THREE.AmbientLight(0xffffff);
var width=window.innerWidth;
var height=window.innerHeight;
camera=new THREE.PerspectiveCamera(75,width/height,0.1,1000);//透视照相机
camera.position.z=18;
renderer=new THREE.WebGLRenderer({
antialias:true,
alpha:true
});
renderer.setSize(width,height);
document.getElementById("webgl-container").appendChild(renderer.domElement);
clock=new THREE.Clock();
var sLight=new THREE.SpotLight(0xffffff);//聚光灯
sLight.position.set(-100,100,100);
scene.add(sLight);
var aLight=new THREE.AmbientLight(0xffffff);//环境光
scene.add(aLight);
}
//3,添加箱子
//箱子容器
function addHolder()
{
holder=new THREE .Object3D();
holder.name="holder"
//装载若干箱子
for(var i=0;i<totalTargets;i++)
{
var ranCol=new THREE.Color();
ranCol.setRGB(Math.random(),Math.random(),Math.random());
var geometry=new THREE.BoxGeometry(2,2,2);
var material=new THREE.MeshPhongMaterial({
color:ranCol,
ambient:ranCol
});
var cube=new THREE.Mesh(geometry,material);
cube.position.x=i*5;
cube.name="cubeName"+i;
var spinner=new THREE.Object3D();
spinner.rotation.x=i*2.5*Math.PI;
spinner.name="spinnerName"+i;
spinner.add(cube);
holder.add(spinner);
};
scene.add(holder);
}
//4,爆炸效果
function addExplosion(point)
{
var timeNow=clock.getElapsedTime();//返回clock类内置时间长度,以秒为单位
//产生四个爆炸物
for(var i=0;i<4;i++)
{
var geometry=new THREE.BoxGeometry(1,1,1);
var material=new THREE.MeshBasicMaterial({
color:0x999999
});
var part=new THREE.Mesh(geometry,material);
part.position.x=point.x;
part.position.y=point.y;
part.position.z=point.z;
part.name="part"+i;
part.birthDay=timeNow;
scene.add(part);
particles.push(part);//增加粒子
};
}
//5,渲染
function render()
{
holder.children.forEach(function(elem,index,array){
elem.rotation.y+=(speed*(6-index));
elem.children[0].rotation.x+=0.01;
elem.children[0].rotation.y+=0.01;
});
if(particles.length>0)//粒子效果
{
particles.forEach(function(elem,index,array){
switch(elem.name)
{
case "part0":
elem.position.x+=1;
break;
case "part1":
elem.position.x-=1;
break;
case "part2":
elem.position.y+=1;
break;
case "part3":
elem.position.y-=1;
break;
default:
break;
}
if(elem.birthDay-clock.getElapsedTime()<-1)
{
scene.remove(elem);
particles.splice(index,1);//删除一个元素
}
})
};
renderer.render(scene,camera);
}
//6,鼠标响应
function onDocumentMouseDown(event)
{
clicktime++;
event.preventDefault();//取消事件默认动作
//如果通关
/*
if(complete)
{
complete=false;
score=0;
restartScene();
return;
}
*/
//计算鼠标坐标
mouse.x=(event.clientX/window.innerWidth)*2-1;
mouse.y=(event.clientY/window.innerHeight)*2-1;
//映射鼠标坐标到照相机
raycaster.setFromCamera(mouse,camera);
//还没通关
if(score<totalTargets)
{
holder.children.forEach(function(elem,index,array){
intersects=raycaster.intersectObjects(elem.children);//射线是否与箱子相交,返回相交数量
if(intersects.length>0 && intersects[0].object.visible)
{
intersects[0].object.visible=false;//箱子不可见
addExplosion(intersects[0].point);//爆炸
score+=1;
if(score<totalTargets)//未通关
{
myScore.innerHTML="<span class='hit'>命中!</span>得分:"+score+"/"+totalTargets;
}
else//通关
{
//complete=true;
if(level<totalLevels)//未达到最后一关
{
myScore.innerHTML="<strong>恭喜过关!</strong>点击按钮进行第"+(level+1)+" 关!";
}
else//达到最后一关
{
now = new Date();
var endtime = now.getMinutes();
var gametime=endtime-starttime;
myScore.innerHTML="<strong>通关成功!</strong>点击按钮重新开始!";
mybutton.innerHTML="重新开始";
alert("点击次数:"+clicktime+" 游戏时间:"+gametime+"分钟");
}
};
}
});
}
}
//7,通关设置
function restartScene()
{
myScore.innerHTML="";
if(level<totalLevels)
{
speed+=0.005;
totalTargets+=1;
level+=1;
}
else
{
speed=0.01;
totalTargets=3;
level=1;
}
myLevel.innerText=comments[level-1]+":第"+level+"关,共"+totalLevels+"关";
scene.remove(holder);
addHolder();
}
//8,其他函数
document.getElementById("webgl-container").addEventListener('mousedown', onDocumentMouseDown, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
render();
}
//重绘
function animate() {
requestAnimationFrame(animate);
render();
}
function xiayiguan()
{
clicktime--;
complete=false;
score=0;
restartScene();
return;
}
function jiansu()
{
speed=speed/5.0;
return;
}
//载入设置
window.onload=function()
{
this.myLevel.innerHTML=comments[this.level-1]+"第:"+level+"关,共"+this.totalLevels+"关";
myScene();
addHolder();
animate();
window.addEventListener('resize',this.onWindowResize,false);
}