一.项目背景
大学时期参加了机器人协会,并有幸成为了视觉组组长,所以在新一届社团招新上做了一款趣味小游戏来吸引新生的眼球,让大家知道协会的视觉组。
二.代码展示
<!DOCTYPE html>
<html>
<head>
<style>
body {
margin: 0;
padding: 0;
background-color: black;
color:white;
font-family: helvetica;
}
canvas {
position: absolute;
}
.hud {
position: absolute;
margin-left: 1em;
}
.hit {
font-weight: bold;
color: red;
}
</style>
</head>
<body>
<script type="text/javascript" src="//wow.techbrood.com/libs/jquery/jquery-2.1.1.min.js"></script><div class="hud">
<h1 align="center">机器人协会百团大战招新小游戏——眼花缭乱(视觉组制作)</h1>
<h1 id="level"></h1>
<p>点击方块,使它消失!!!</p>
<p id="score"></p>
<p>
计时器:<span id="sp1"> 71</span>秒
</p>
</div>
<div id="webgl-container"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r70/three.min.js"></script>
<script>
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 = 3;
var speed = 0.01;
var complete = false;
var comments = ["简单", "一般", "困难", "超困难"];
var myLevel = document.getElementById("level");
var myScore = document.getElementById("score");
var raycaster = new THREE.Raycaster();
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);
}
function spinner() {
var geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshPhongMaterial({
color: "hotpink",
ambient: "hotpink"
});
var cube = new THREE.Mesh(geometry, material);
cube.position.x = 10;
var spinner = new THREE.Object3D();
spinner.rotation.x = 6;
spinner.add(cube);
scene.add(spinner);
}
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);
}
function addExplosion(point) {
var timeNow = clock.getElapsedTime();
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);
};
}
function animate() {
requestAnimationFrame(animate);
render();
}
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);
}
function onDocumentMouseDown(event) {
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: " + score + "/" + totalTargets;
} else {
complete = true;
if (level < totalLevels) {
myScore.innerHTML = "<strong>你消灭了全部</strong> 点击屏幕进入下一等级 " + (level + 1) + ".";
} else {
myScore.innerHTML = "<strong>你胜利啦,快去找社团负责人领取奖品吧!</strong> ";
alert("你胜利啦,快去找社团负责人领取奖品吧!请点击刷新以重新开始游戏。");
}
};
}
});
}
}
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 " + level + " of " + totalLevels;
scene.remove(holder);
addHolder();
}
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();
}
window.onload = function() {
myLevel.innerText = comments[level - 1] + ": Level " + level + " of " + totalLevels;
myScene();
addHolder();
animate();
window.addEventListener('resize', onWindowResize, false);
};
var sp1 =document.getElementById("sp1").innerHTML;
var time = setInterval(function () {
if(level===1&&sp1==71){
alert("请仔细观看左边的规则哦!!!熟悉规则后按确定开始游戏!!!")
}
if(sp1===0&&level!=1){
sp1=1;
}
sp1 = sp1-1;
document.getElementById("sp1").innerHTML =sp1;
if (sp1 ===0){
alert("你失败了!");
}
if(sp1===0){
if(level ===1){
sp1=71;
}
}
},1000)
</script>
</body>
</html>
三.项目使用方法
桌面新建txt文本文件。
将代码复制到文本文件中。
修改文件后缀名。
双击文件就可以打开了,最好使用google浏览器,并且第一次打开速度比较慢。