Flower图案
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>flower</title>
<style>
* {
margin: 0;
padding: 0;
overflow: hidden;
background-color: black;
}
</style>
</head>
<body>
<canvas id="c"></canvas>
<script>
var C = document.getElementById("c");
var Ctx = C.getContext("2d");
var Cw = C.width = window.innerWidth,
Cx = Cw / 2;
var Ch = C.height = window.innerHeight,
Cy = Ch / 2;
var c = document.createElement("canvas");
var ctx = c.getContext("2d");
var cw = c.width = 400,
cx = cw / 2;
var ch = c.height = 400,
cy = ch / 2;
var rad = Math.PI / 180;
var frames = 0;
var stopped = true;
var Rx = 150,
Ry = 150,
kx = 3,
ky = 4,
x, y, x1, y1, x2, y2, t;
var petals = 7;
ctx.strokeStyle ="#b43c44";
ctx.globalAlpha = .5;
ctx.lineWidth = .25;
Ctx.translate(Cw / 2, Ch / 2);
Ctx.scale(.75, .75)
function Draw() {
frames += .3;
Ctx.clearRect(-Cw, -Ch, 2 * Cw, 2 * Ch);
t = frames * rad;
rx = Rx * Math.abs(Math.cos(t)) + 50;
ry = Ry * Math.abs(Math.sin(t)) + 50;
x = cx + rx * Math.sin(kx * t + Math.PI / 2);
y = cy + ry * Math.sin(ky * t + Math.PI / 2);
x1 = cx + rx * Math.sin(kx * t + Math.PI);
y1 = cy - ry * Math.sin(ky * t + Math.PI);
x2 = cx + rx * Math.sin(kx * t);
y2 = cy - ry * Math.sin(ky * t);
ctx.beginPath();
ctx.moveTo(x, y);
ctx.quadraticCurveTo(x1, y1, x2, y2);
ctx.stroke();
ctx.globalCompositeOperation = "lighter";
var img = c;
//Ctx[i].fillRect(-cw, -ch, cw, ch);
for (var i = 0; i < petals; i++) {
Ctx.globalCompositeOperation = "source-over";
Ctx.drawImage(img, -200, -400);
Ctx.rotate(2 * Math.PI / petals);
}
requestId = window.requestAnimationFrame(Draw);
}
function start() {
requestId = window.requestAnimationFrame(Draw);
stopped = false;
}
function stopAnim() {
if (requestId) {
window.cancelAnimationFrame(requestId);
}
stopped = true;
}
window.addEventListener("load", function() {
start();
}, false);
function cleanSlate() {
ctx.clearRect(0, 0, cw, ch);
stopped = true;
start();
window.setTimeout(function() {
stopAnim();
}, 30000);
}
window.setTimeout(function() {
stopAnim();
}, 30000);
C.addEventListener("click", function() {
cleanSlate()
}, false);
</script>
</body>
</html>
PI图形计算
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>PI图形计算</title>
</head>
<body>
<canvas id="canvas_img"></canvas>
</body>
<script type="text/javascript">
d = document;
canvas_img = document.getElementById('canvas_img');
context = canvas_img.getContext('2d');
time = 5;
w = canvas_img.width = innerWidth;
h = canvas_img.height = innerHeight;
m = Math;
cos = m.cos;
sin = m.sin;
PI = m.PI;
setInterval(function() {
canvas_img.width = canvas_img.width;
time += .2;
i = 5000;
while (i--) {
r = (w + h) / 2 * (m.cos((time + i) * (.15 + (m.sin(time / 15000) / PI * .2))) / PI);
if(i<3333){
context.fillStyle = 'green';
}else if(i<6666){
context.fillStyle = 'red';
}else{
context.fillStyle = 'black';
}
context.fillRect(m.sin(i)*r + w / 2,m.cos(i) * r + h / 2,1.5,1.5);
}
}, 1);
</script>
</html>
WebGL魔方小游戏
<!DOCTYPE html>
<html ng-app="starter">
<head>
<title>WebGL魔方小游戏</title>
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
* {
padding: 0px;
margin: 0px;
overflow: hidden;
background: #000;
}
</style>
</head>
<body>
<canvas id="canvas" width="512" height="512"></canvas>
<script type="text/x-glsl" id="svShader">
attribute vec3 position; attribute vec3 normal; attribute vec3 color; uniform mat4 mMatrix; uniform mat4 mvpMatrix; uniform mat4 mvpShadowerMatrix; uniform vec3 lVector; varying float diffuse; varying vec4 vPosition; varying vec3 vColor; void main(){ vec4 v4Position=vec4(position,1.0); vPosition=mvpShadowerMatrix*v4Position; gl_Position=mvpMatrix*v4Position; vec3 tNormal=(mMatrix*vec4(normalize(normal),0.0)).xyz; diffuse=max(-dot(tNormal,normalize(lVector)),0.4); vColor=color; }
</script>
<script type="text/x-glsl" id="sfShader">
precision lowp float; varying float diffuse; uniform sampler2D depthData; uniform vec2 size; varying vec4 vPosition; varying vec3 vColor; vec2 depthMap; float f(float i,float j){ float z=texture2D(depthData,depthMap+vec2(i,j)*2.0/size).z; return abs(z-vPosition.z)
<0.01?diffuse:0.4; } void main(){ depthMap=(vPosition.xy/vPosition.w*0.5+0.5)/512.0*size; float vDiffuse=0.0; for(float i=-2.0;i<=2.0;i++)for(float j=-2.0;j<=2.0;j++)vDiffuse+=f(i,j); vDiffuse/=25.0; gl_FragColor=vec4(vec3(vDiffuse*vColor),1.0); } </script>
<script type="text/x-glsl" id="pvShader">
attribute vec3 position; attribute vec3 normal; attribute vec3 color; uniform mat4 mvpMatrix; varying float xx; void main(){ gl_Position=mvpMatrix*vec4(position,1.0); normal;color; }
</script>
<script type="text/x-glsl" id="pfShader">
precision lowp float; uniform float index; void main(){ gl_FragColor=vec4(vec3(index),1.0); }
</script>
<script type="text/x-glsl" id="bvShader">
attribute vec3 position; uniform mat4 mvpShadowerMatrix; varying float depth; void main(){ gl_Position=mvpShadowerMatrix*vec4(position,1.0); depth=gl_Position.z; }
</script>
<script type="text/x-glsl" id="bfShader">
varying lowp float depth; void main(){ gl_FragColor=vec4(vec3(depth),1.0); }
</script>
<script src="http://www.web-tinker.com/files/SimpleWebGL.2.0.js"></script>
<script src="http://www.web-tinker.com/files/SimpleWebGL.Matrix.1.0.js"></script>
<script>
new SimpleWebGL(canvas).namespace(function(
Program, VertexShader, FragmentShader, ArrayBuffer,
Framebuffer, Renderbuffer, Texture2D, Matrix
) {
//基本函数
var π = Math.PI,
sin = Math.sin,
cos = Math.cos,
acos = Math.acos,
pow = Math.pow,
abs = Math.abs,
round = Math.round,
random = Math.random,
updateMvpMatrix = function() {
this.data.mvpMatrix = new Matrix(this.data.mMatrix).multiply(vpMatrix);
this.data.mvpShadowerMatrix = new Matrix(this.data.mMatrix).multiply(vpShadowerMatrix);
};
//定义方块
var Cube;
(function() {
var i, j, k, p, n, position = [],
normal = [],
color = [],
push = Array.prototype.push,
a = 1,
b = 0.9,
ctab = [
[1, 1, 0],
[0, 0, 1],
[1, 0, 0],
[1, 1, 1],
[0, 1, 0],
[1, 0.5, 0]
];
for(i = 0; i < 2; i++)
for(j = 0; j < 3; j++) { //面
for(k = 0; k < 4; k++)
p = [k >> 1 ? b : -b, k & 1 ? b : -b], p.splice(j, 0, i ? a : -a), push.apply(position, p),
n = [0, 0], n.splice(j, 0, i ? a : -a), push.apply(normal, n),
push.apply(color, ctab[i * 3 + j]);
push.apply(position, position.slice(-9, -3));
push.apply(normal, normal.slice(-9, -3));
push.apply(color, color.slice(-9, -3));
};
for(i = 0; i < 3; i++)
for(j = 0; j < 4; j++) { //棱
for(k = 0; k < 4; k++)
p = k < 2 ? [a, b] : [b, a], p[0] *= j & 2 ? 1 : -1, p[1] *= j & 1 ? 1 : -1,
p.splice(i, 0, (k & 1 ? 1 : -1) * b), push.apply(position, p),
n = [a * (j & 2 ? 1 : -1), a * (j & 1 ? 1 : -1)], n.splice(i, 0, 0), push.apply(normal, n);
push.apply(position, position.slice(-9, -3));
push.apply(normal, normal.slice(-9, -3));
for(k = 0; k < 6; k++) color.push(0.5, 0.5, 0.5);
};
for(i = 0; i < 8; i++)
for(j = 0; j < 3; j++) { //角
for(k = 0; k < 3; k++)
position.push((k == j ? a : b) * (i & 1 << k ? 1 : -1)),
normal.push(a * (i & 1 << k ? 1 : -1));
color.push(0.5, 0.5, 0.5);
};
var count = position.length / 3,
buffers = {
position: new ArrayBuffer(position),
normal: new ArrayBuffer(normal),
color: new ArrayBuffer(color)
};
Cube = function() {
this.data = Object.create(buffers);
};
Cube.prototype = {
update: updateMvpMatrix,
valueOf: function() {
return count;
}
};
})();
//生成操作对象
var cubes = [],
ground;
cubes.dimension = 3,
cubes.translation = Matrix.model([0, 2, 0]);
cubes.rotation = Matrix.model([]).pitch(60).yaw(40).pitch(10);
cubes.wMatrix = new Matrix(cubes.rotation).multiply(cubes.translation);
(function(d) {
var i, j, k, o, e = (cubes.dimension - 1) / 2;
for(i = 0; i < d; i++)
for(j = 0; j < d; j++)
for(k = 0; k < d; k++)
cubes.push(o = new Cube()),
o.location = [i, j, k], o.rotation = new Matrix(4),
o.translation = [i * 2 - d + 1, j * 2 - d + 1, k * 2 - d + 1],
o.m = Matrix.model(o.translation),
o.data.mMatrix = new Matrix(o.m).multiply(cubes.wMatrix),
o.rotate = function(m, r) {
this.location = Matrix.model(this.location).move(-e, -e, -e)[m](r * 90).move(e, e, e).slice(-4, -1).map(round);
this.m = Matrix.model(this.translation).multiply(this.rotation[m](r * 90));
};
})(cubes.dimension);
(function(i, j, k) {
ground = {
update: updateMvpMatrix,
data: {
position: new ArrayBuffer([-i, 0, -j, -i, 0, j, i, 0, -j, i, 0, j, -i, 0, j, i, 0, -j]),
normal: new ArrayBuffer([0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0]),
color: new ArrayBuffer([].concat(k, k, k, k, k, k)),
mMatrix: Matrix.model([0, -7, -9])
},
valueOf: function() {
return 6;
}
};
})(7, 12, [0.5, 0.5, 0.5]);
//打乱
(function shuffle(c) {
var d = cubes.dimension,
dir = random() * d | 0,
m = ["pitch", "yaw", "roll"][dir],
r = random() * 3 + 1 | 0,
cur = random() * d | 0,
offset = (d - 1) / 2,
group = [],
i, o;
for(i = 0; o = cubes[i]; i++)
if(o.location[dir] == cur) group.push(o);
for(i = 0; o = group[i]; i++) o.rotate(m, r), o.data.mMatrix = new Matrix(o.m).multiply(cubes.wMatrix);
if(c-- > 0) shuffle(c);
})(30);
//定义矩阵
var vpMatrix = Matrix.view([0, 0, 32]).multiply(
Matrix.projection(30, canvas.width / canvas.height, 0.01, 200)
),
lVector = [-0, -8, -8],
vpShadowerMatrix = Matrix.view( //光
[-lVector[0], -lVector[1], -lVector[2]],
acos(-lVector[2] / pow(pow(lVector[0], 2) + pow(lVector[2], 2), 0.5)) / π * 180, -acos(-lVector[2] / pow(pow(lVector[1], 2) + pow(lVector[2], 2), 0.5)) / π * 180
).multiply(new Matrix(4).data(2, 2, -1 / 32).data(3, 3, 9).data(3, 1, -1.2));
//初始化着色器
var picker = new Program(new VertexShader(pvShader), new FragmentShader(pfShader)).link(),
shadower = new Program(new VertexShader(bvShader), new FragmentShader(bfShader)).link(),
stage = new Program(new VertexShader(svShader), new FragmentShader(sfShader)).link();
stage.use().data({
size: [canvas.width, canvas.height],
lVector: lVector
});
//初始化缓冲区
var frameTexture = new Texture2D(null, "RGBA", 512, 512).bind(0),
framebuffer = new Framebuffer(new Renderbuffer("DEPTH_COMPONENT16", 512, 512), frameTexture).unbind();
//播放帧
var active;
this.play(function() {
var i, o, l = cubes.length;
for(i = 0; i < l; i++) cubes[i].update();
ground.update();
if(MBUTTON == null) {
framebuffer.bind(), this.clear("COLOR", "DEPTH"), picker.use();
for(i = 0; o = cubes[i]; i++) picker.data(o.data).data({
index: (i + 1) / l
}).draw(o);
active = round(frameTexture.readPixels(MX, 512 - MY)[0] / 0xFF * l - 1);
};
framebuffer.bind(), this.clear("COLOR", "DEPTH"), shadower.use();
for(i = 0; o = cubes[i]; i++) shadower.data(o.data).draw(o);
shadower.data(ground.data).draw(ground);
framebuffer.unbind(), this.clear("COLOR", "DEPTH"), stage.use();
for(i = 0; o = cubes[i]; i++) stage.data(o.data).draw(o);
stage.data(ground.data).draw(ground);
}).setting({
DEPTH_TEST: "LESS"
}).color(0, 0, 0, 1);
//鼠标操作
var MX, MY, MBUTTON;
(function() {
addEventListener("contextmenu", function(e) {
e.preventDefault();
});
addEventListener("mousedown", function(e) {
MBUTTON = e.button;
});
addEventListener("mouseup", function(e) {
MBUTTON = null;
});
addEventListener("mousemove", function(e) {
MX = e.layerX, MY = e.layerY;
});
//元素拖拽
var queue = [],
offset = (cubes.dimension - 1) / 2;
addEventListener("mousedown", function(e) {
if(e.button != 0 || active < 0) return;
var i, j, o, dir, mx = e.clientX,
my = e.clientY,
mousemove, mouseup,
groups = [
[],
[],
[]
],
methods = ["pitch", "yaw", "roll"],
mpos;
for(i = 0; o = cubes[i]; i++)
for(j = 0; j < 3; j++)
if(o.location[j] == cubes[active].location[j]) groups[j].push(o);
addEventListener("mousemove", mousemove = function(e) {
var ndir, group, i, j, o;
mpos = Matrix.model([(e.clientY - my) / 2, (e.clientX - mx) / 2, 0]).multiply(new Matrix(cubes.wMatrix).inverse()).slice(-4, -1);
group = groups[o = mpos.map(abs), ndir = o.indexOf(Math.max.apply(Math, o))];
if(dir != ndir)
for(i = 0; i < queue.length; i++)
for(j = 0; j < group.length; j++)
if(queue[i].indexOf(group[j]) > -1) ndir = dir, j = group.length, i = queue.length;
if(dir != void 0 && dir != ndir)
for(i = 0; o = groups[dir][i]; i++) o.data.mMatrix = new Matrix(o.m).multiply(cubes.wMatrix);
if(group = groups[dir = ndir])
for(i = 0; o = group[i]; i++)
o.data.mMatrix = new Matrix(o.m)[methods[dir]](mpos[dir]).multiply(cubes.wMatrix);
}), addEventListener("mouseup", mouseup = function() {
removeEventListener("mousemove", mousemove), removeEventListener("mouseup", mouseup);
var m = methods[dir],
r = round(mpos[dir] / 90) % 4,
group = groups[dir],
i, o, r;
if(!group) return;
queue.push(group);
for(i = 0; o = group[i]; i++) o.rotate(m, r);
if(r = mpos[dir] %= 90)
if(abs(r) > 45) r = r < 0 ? 90 - abs(r) : abs(r) - 90;
(function callee() {
if(abs(r *= 0.7) < 0.5) r = 0;
for(i = 0; o = group[i]; i++) o.data.mMatrix = new Matrix(o.m)[m](r).multiply(cubes.wMatrix);
if(r) setTimeout(callee, 16);
else queue.splice(queue.indexOf(group), 1);
})()
});
});
//控制方向
addEventListener("mousedown", function(e) {
if(e.button != 2) return;
var x = e.clientX,
y = e.clientY,
mousemove, mouseup;
addEventListener("mousemove", mousemove = function(e) {
cubes.rotation.yaw((e.clientX - x) / 2).pitch((e.clientY - y) / 2);
cubes.wMatrix = new Matrix(cubes.rotation).multiply(cubes.translation);
for(var i = 0, o; o = cubes[i]; i++) o.data.mMatrix = new Matrix(o.m).multiply(cubes.wMatrix);
x = e.clientX, y = e.clientY;
}), addEventListener("mouseup", mouseup = function(e) {
removeEventListener("mousemove", mousemove), removeEventListener("mouseup", mouseup);
});
});
})();
});
</script>
</body>
</html>
打气球
</head>
<body>
<script>
var num = 10;/*初次生成的数量*/
var wH = window.innerHeight;
var wW = window.innerWidth;
var bH = 160;
var balloons=[];
var timer=null;
/*事件代理 监听body上所有的点击事件*/
document.body.addEventListener('click',function(event){
/*判断event对象是否是需要的元素*/
if (event.target.className==='balloon'){
//event.target.parentNode.removeChild(event.target);
boom.call(event.target,function(){
this.parentNode.removeChild(this);
init(1);
}.bind(event.target));
}
});
function boom(cb){
this.timer =setInterval(function(){
if(this.offsetWidth<10){
clearInterval(this.timer);
cb&&cb();
}
this.speed++;
this.style.width=this.offsetWidth-10+'px';
this.style.height=this.offsetHeight-10+'px';
}.bind(this),1000/30)
}
function init(num){
var fragment = document.createDocumentFragment();/*创建dom片段*/
for(var i=0 ;i<num ;i++){
var randomX = ~~(Math.random()*(wW-bH) );
randomX = Math.max(0,randomX);
var oBalloon = document.createElement('div');/*创建一个div*/
oBalloon.className='balloon';/*添加类名*/
oBalloon.style.top= wH - bH +'px';
oBalloon.style.left=randomX+'px';
oBalloon.speed=~~(Math.random()*8)+1;/*自定义speed属性*/
balloons.push(oBalloon);
fragment.appendChild(oBalloon);/*添加到body中*/
}
document.body.appendChild(fragment);
}
init(num);/*执行初始化*/
function move (){
//获取所有气球
for (var i =0,len=balloons.length;i<len;i++){
balloons[i].style.top=balloons[i].offsetTop-balloons[i].speed+'px';
}
}
function recall(){
move ();
timer = setTimeout(arguments.callee,1000/30);/*递归保证动画稳定性*/
}
recall();
</script>
</body>
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190608234643868.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3podXhpb25neWlu,size_16,color_FFFFFF,t_70) # 倒计时
<!DOCTYPE html>
<html>
<head>
<style>
*{border:0.0px solid red;}
p{font-size:28px;
color:red;
margin:60px 42px;
}
input{
height:50px;width:80px;
font-size:16px;
}
</style>
<script>
window.onload=function(){
var begin=document.querySelector("#begin");
var stop=document.getElementById('stop');
var clear=document.getElementById('clear');
var p=document.getElementById('p');
var init="00:00:00";
var hidd=document.querySelector('#hidd');
var n=0;//1/10秒
var sec=0;//秒
var min=0;//分钟
//初始
p.innerHTML=init;
var int;
var isGo=false; //是否已经启动
//绑定事件 绑定事件其实是相当于 可以重复多次调用这个函数 因为只要满足触发条件 就跑了
begin.onclick=function(){
if(!isGo){
int=setInterval(
function(){
n++;
if(n==100) {sec++; n=0;}
if(sec==60) {min++;sec=0;}
p.innerHTML=(min<10?("0"+min):min)+":"+(sec<10?("0"+sec):sec)+":"+n; //如果是小于10 前面加个0字符串
if(sec==30) hidd.removeAttribute("hidden"); //在跑这个线程同时判断 如果sec到了两秒 就解禁
}
,10);
isGo=true;}
};
/*
如果点击一下已启动状态是清除函数 即暂停效果 再次点击 如果是未启动状态 就启动他
*/
stop.onclick=function(){
if(isGo){
clearInterval(int); //如果这个int是undefined就不起作用
isGo=false;
}else{
begin.onclick();
}
};
/*
清除点击即清0
*/
clear.onclick=function(){
clearInterval(int);
min=0;sec=0;n=0;
p.innerHTML=init;
hidd.setAttribute("hidden",'');
isGo=false;
};
};
</script>
</head>
<body>
<p id='p'></p>
<input type="button" value="开始" id='begin' />
<input type="button" value='stop/继续' id='stop'/>
<input type="button" value='清除' id='clear'/>
<p hidden id="hidd">我喜欢你呀!哈哈</p>
</body>
</html>
兔子快跑-170931289
<!DOCTYPE html>
<html>
<head>
<title>兔子快跑-170931289</title>
<meta charset='UTF-8'>
<meta name="robots" content="noindex">
<script src='https://cdnjs.cloudflare.com/ajax/libs/three.js/r80/three.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.0/TweenMax.min.js'></script>
<script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/264161/OrbitControls.js'></script>
<script type="text/javascript">
var scene,
camera, fieldOfView, aspectRatio, nearPlane, farPlane,
gobalLight, shadowLight, backLight,
renderer,
container,
controls,
clock;
var delta = 0;
var floorRadius = 200;
var speed = 6;
var distance = 0;
var level = 1;
var levelInterval;
var levelUpdateFreq = 3000;
var initSpeed = 5;
var maxSpeed = 48;
var monsterPos = .65;
var monsterPosTarget = .65;
var floorRotation = 0;
var collisionObstacle = 10;
var collisionBonus = 20;
var gameStatus = "play";
var cameraPosGame = 160;
var cameraPosGameOver = 260;
var monsterAcceleration = 0.004;
var malusClearColor = 0xb44b39;
var malusClearAlpha = 0;
var audio = new Audio('https://s3-us-west-2.amazonaws.com/s.cdpn.io/264161/Antonio-Vivaldi-Summer_01.mp3');
var fieldGameOver, fieldDistance;
//屏幕和鼠标变量
var HEIGHT, WIDTH, windowHalfX, windowHalfY,
mousePos = {
x: 0,
y: 0
};
//3D对象变量
var hero;
// 材料
var blackMat = new THREE.MeshPhongMaterial({
color: 0x100707,
shading: THREE.FlatShading,
});
var brownMat = new THREE.MeshPhongMaterial({
color: 0xb44b39,
shininess: 0,
shading: THREE.FlatShading,
});
var greenMat = new THREE.MeshPhongMaterial({
color: 0x7abf8e,
shininess: 0,
shading: THREE.FlatShading,
});
var pinkMat = new THREE.MeshPhongMaterial({
color: 0xdc5f45,
shininess: 0,
shading: THREE.FlatShading,
});
var lightBrownMat = new THREE.MeshPhongMaterial({
color: 0xe07a57,
shading: THREE.FlatShading,
});
var whiteMat = new THREE.MeshPhongMaterial({
color: 0xa49789,
shading: THREE.FlatShading,
});
var skinMat = new THREE.MeshPhongMaterial({
color: 0xff9ea5,
shading: THREE.FlatShading
});
// 其他变量
var PI = Math.PI;
//初始化三个JS,屏幕和鼠标事件
function initScreenAnd3D() {
HEIGHT = window.innerHeight;
WIDTH = window.innerWidth;
windowHalfX = WIDTH / 2;
windowHalfY = HEIGHT / 2;
scene = new THREE.Scene();
scene.fog = new THREE.Fog(0xd6eae6, 160, 350);
aspectRatio = WIDTH / HEIGHT;
fieldOfView = 50;
nearPlane = 1;
farPlane = 2000;
camera = new THREE.PerspectiveCamera(
fieldOfView,
aspectRatio,
nearPlane,
farPlane
);
camera.position.x = 0;
camera.position.z = cameraPosGame;
camera.position.y = 30;
camera.lookAt(new THREE.Vector3(0, 30, 0));
renderer = new THREE.WebGLRenderer({
alpha: true,
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setClearColor(malusClearColor, malusClearAlpha);
renderer.setSize(WIDTH, HEIGHT);
renderer.shadowMap.enabled = true;
container = document.getElementById('world');
container.appendChild(renderer.domElement);
window.addEventListener('resize', handleWindowResize, false);
document.addEventListener('mousedown', handleMouseDown, false);
document.addEventListener("touchend", handleMouseDown, false);
clock = new THREE.Clock();
}
function handleWindowResize() {
HEIGHT = window.innerHeight;
WIDTH = window.innerWidth;
windowHalfX = WIDTH / 2;
windowHalfY = HEIGHT / 2;
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
}
function handleMouseDown(event) {
if(gameStatus == "play") hero.jump();
else if(gameStatus == "readyToReplay") {
replay();
}
}
function createLights() {
globalLight = new THREE.AmbientLight(0xffffff, .9);
shadowLight = new THREE.DirectionalLight(0xffffff, 1);
shadowLight.position.set(-30, 40, 20);
shadowLight.castShadow = true;
shadowLight.shadow.camera.left = -400;
shadowLight.shadow.camera.right = 400;
shadowLight.shadow.camera.top = 400;
shadowLight.shadow.camera.bottom = -400;
shadowLight.shadow.camera.near = 1;
shadowLight.shadow.camera.far = 2000;
shadowLight.shadow.mapSize.width = shadowLight.shadow.mapSize.height = 2048;
scene.add(globalLight);
scene.add(shadowLight);
}
function createFloor() {
floorShadow = new THREE.Mesh(new THREE.SphereGeometry(floorRadius, 50, 50), new THREE.MeshPhongMaterial({
color: 0x7abf8e,
specular: 0x000000,
shininess: 1,
transparent: true,
opacity: .5
}));
floorShadow.receiveShadow = true;
floorGrass = new THREE.Mesh(new THREE.SphereGeometry(floorRadius - .5, 50, 50), new THREE.MeshBasicMaterial({
color: 0x7abf8e
}));
floorGrass.receiveShadow = false;
floor = new THREE.Group();
floor.position.y = -floorRadius;
floor.add(floorShadow);
floor.add(floorGrass);
scene.add(floor);
}
Hero = function() {
this.status = "running";
this.runningCycle = 0;
this.mesh = new THREE.Group();
this.body = new THREE.Group();
this.mesh.add(this.body);
var torsoGeom = new THREE.CubeGeometry(7, 7, 10, 1);
this.torso = new THREE.Mesh(torsoGeom, brownMat);
this.torso.position.z = 0;
this.torso.position.y = 7;
this.torso.castShadow = true;
this.body.add(this.torso);
var pantsGeom = new THREE.CubeGeometry(9, 9, 5, 1);
this.pants = new THREE.Mesh(pantsGeom, whiteMat);
this.pants.position.z = -3;
this.pants.position.y = 0;
this.pants.castShadow = true;
this.torso.add(this.pants);
var tailGeom = new THREE.CubeGeometry(3, 3, 3, 1);
tailGeom.applyMatrix(new THREE.Matrix4().makeTranslation(0, 0, -2));
this.tail = new THREE.Mesh(tailGeom, lightBrownMat);
this.tail.position.z = -4;
this.tail.position.y = 5;
this.tail.castShadow = true;
this.torso.add(this.tail);
this.torso.rotation.x = -Math.PI / 8;
var headGeom = new THREE.CubeGeometry(10, 10, 13, 1);
headGeom.applyMatrix(new THREE.Matrix4().makeTranslation(0, 0, 7.5));
this.head = new THREE.Mesh(headGeom, brownMat);
this.head.position.z = 2;
this.head.position.y = 11;
this.head.castShadow = true;
this.body.add(this.head);
var cheekGeom = new THREE.CubeGeometry(1, 4, 4, 1);
this.cheekR = new THREE.Mesh(cheekGeom, pinkMat);
this.cheekR.position.x = -5;
this.cheekR.position.z = 7;
this.cheekR.position.y = -2.5;
this.cheekR.castShadow = true;
this.head.add(this.cheekR);
this.cheekL = this.cheekR.clone();
this.cheekL.position.x = -this.cheekR.position.x;
this.head.add(this.cheekL);
var noseGeom = new THREE.CubeGeometry(6, 6, 3, 1);
this.nose = new THREE.Mesh(noseGeom, lightBrownMat);
this.nose.position.z = 13.5;
this.nose.position.y = 2.6;
this.nose.castShadow = true;
this.head.add(this.nose);
var mouthGeom = new THREE.CubeGeometry(4, 2, 4, 1);
mouthGeom.applyMatrix(new THREE.Matrix4().makeTranslation(0, 0, 3));
mouthGeom.applyMatrix(new THREE.Matrix4().makeRotationX(Math.PI / 12));
this.mouth = new THREE.Mesh(mouthGeom, brownMat);
this.mouth.position.z = 8;
this.mouth.position.y = -4;
this.mouth.castShadow = true;
this.head.add(this.mouth);
var pawFGeom = new THREE.CubeGeometry(3, 3, 3, 1);
this.pawFR = new THREE.Mesh(pawFGeom, lightBrownMat);
this.pawFR.position.x = -2;
this.pawFR.position.z = 6;
this.pawFR.position.y = 1.5;
this.pawFR.castShadow = true;
this.body.add(this.pawFR);
this.pawFL = this.pawFR.clone();
this.pawFL.position.x = -this.pawFR.position.x;
this.pawFL.castShadow = true;
this.body.add(this.pawFL);
var pawBGeom = new THREE.CubeGeometry(3, 3, 6, 1);
this.pawBL = new THREE.Mesh(pawBGeom, lightBrownMat);
this.pawBL.position.y = 1.5;
this.pawBL.position.z = 0;
this.pawBL.position.x = 5;
this.pawBL.castShadow = true;
this.body.add(this.pawBL);
this.pawBR = this.pawBL.clone();
this.pawBR.position.x = -this.pawBL.position.x;
this.pawBR.castShadow = true;
this.body.add(this.pawBR);
var earGeom = new THREE.CubeGeometry(7, 18, 2, 1);
earGeom.vertices[6].x += 2;
earGeom.vertices[6].z += .5;
earGeom.vertices[7].x += 2;
earGeom.vertices[7].z -= .5;
earGeom.vertices[2].x -= 2;
earGeom.vertices[2].z -= .5;
earGeom.vertices[3].x -= 2;
earGeom.vertices[3].z += .5;
earGeom.applyMatrix(new THREE.Matrix4().makeTranslation(0, 9, 0));
this.earL = new THREE.Mesh(earGeom, brownMat);
this.earL.position.x = 2;
this.earL.position.z = 2.5;
this.earL.position.y = 5;
this.earL.rotation.z = -Math.PI / 12;
this.earL.castShadow = true;
this.head.add(this.earL);
this.earR = this.earL.clone();
this.earR.position.x = -this.earL.position.x;
this.earR.rotation.z = -this.earL.rotation.z;
this.earR.castShadow = true;
this.head.add(this.earR);
var eyeGeom = new THREE.CubeGeometry(2, 4, 4);
this.eyeL = new THREE.Mesh(eyeGeom, whiteMat);
this.eyeL.position.x = 5;
this.eyeL.position.z = 5.5;
this.eyeL.position.y = 2.9;
this.eyeL.castShadow = true;
this.head.add(this.eyeL);
var irisGeom = new THREE.CubeGeometry(.6, 2, 2);
this.iris = new THREE.Mesh(irisGeom, blackMat);
this.iris.position.x = 1.2;
this.iris.position.y = 1;
this.iris.position.z = 1;
this.eyeL.add(this.iris);
this.eyeR = this.eyeL.clone();
this.eyeR.children[0].position.x = -this.iris.position.x;
this.eyeR.position.x = -this.eyeL.position.x;
this.head.add(this.eyeR);
this.body.traverse(function(object) {
if(object instanceof THREE.Mesh) {
object.castShadow = true;
object.receiveShadow = true;
}
});
}
BonusParticles = function() {
this.mesh = new THREE.Group();
var bigParticleGeom = new THREE.CubeGeometry(10, 10, 10, 1);
var smallParticleGeom = new THREE.CubeGeometry(5, 5, 5, 1);
this.parts = [];
for(var i = 0; i < 10; i++) {
var partPink = new THREE.Mesh(bigParticleGeom, pinkMat);
var partGreen = new THREE.Mesh(smallParticleGeom, greenMat);
partGreen.scale.set(.5, .5, .5);
this.parts.push(partPink);
this.parts.push(partGreen);
this.mesh.add(partPink);
this.mesh.add(partGreen);
}
}
BonusParticles.prototype.explose = function() {
var _this = this;
var explosionSpeed = .5;
for(var i = 0; i < this.parts.length; i++) {
var tx = -50 + Math.random() * 100;
var ty = -50 + Math.random() * 100;
var tz = -50 + Math.random() * 100;
var p = this.parts[i];
p.position.set(0, 0, 0);
p.scale.set(1, 1, 1);
p.visible = true;
var s = explosionSpeed + Math.random() * .5;
TweenMax.to(p.position, s, {
x: tx,
y: ty,
z: tz,
ease: Power4.easeOut
});
TweenMax.to(p.scale, s, {
x: .01,
y: .01,
z: .01,
ease: Power4.easeOut,
onComplete: removeParticle,
onCompleteParams: [p]
});
}
}
function removeParticle(p) {
p.visible = false;
}
Hero.prototype.run = function() {
this.status = "running";
var s = Math.min(speed, maxSpeed);
this.runningCycle += delta * s * .7;
this.runningCycle = this.runningCycle % (Math.PI * 2);
var t = this.runningCycle;
var amp = 4;
var disp = .2;
// 身体
this.body.position.y = 6 + Math.sin(t - Math.PI / 2) * amp;
this.body.rotation.x = .2 + Math.sin(t - Math.PI / 2) * amp * .1;
this.torso.rotation.x = Math.sin(t - Math.PI / 2) * amp * .1;
this.torso.position.y = 7 + Math.sin(t - Math.PI / 2) * amp * .5;
// 口
this.mouth.rotation.x = Math.PI / 16 + Math.cos(t) * amp * .05;
// 头
this.head.position.z = 2 + Math.sin(t - Math.PI / 2) * amp * .5;
this.head.position.y = 8 + Math.cos(t - Math.PI / 2) * amp * .7;
this.head.rotation.x = -.2 + Math.sin(t + Math.PI) * amp * .1;
// 耳朵
this.earL.rotation.x = Math.cos(-Math.PI / 2 + t) * (amp * .2);
this.earR.rotation.x = Math.cos(-Math.PI / 2 + .2 + t) * (amp * .3);
// 眼睛
this.eyeR.scale.y = this.eyeL.scale.y = .7 + Math.abs(Math.cos(-Math.PI / 4 + t * .5)) * .6;
// 尾巴
this.tail.rotation.x = Math.cos(Math.PI / 2 + t) * amp * .3;
//前爪
// 右
this.pawFR.position.y = 1.5 + Math.sin(t) * amp;
this.pawFR.rotation.x = Math.cos(t) * Math.PI / 4;
this.pawFR.position.z = 6 - Math.cos(t) * amp * 2;
// 左
this.pawFL.position.y = 1.5 + Math.sin(disp + t) * amp;
this.pawFL.rotation.x = Math.cos(t) * Math.PI / 4;
this.pawFL.position.z = 6 - Math.cos(disp + t) * amp * 2;
//后爪
// 右
this.pawBR.position.y = 1.5 + Math.sin(Math.PI + t) * amp;
this.pawBR.rotation.x = Math.cos(t + Math.PI * 1.5) * Math.PI / 3;
this.pawBR.position.z = -Math.cos(Math.PI + t) * amp;
// 左
this.pawBL.position.y = 1.5 + Math.sin(Math.PI + t) * amp;
this.pawBL.rotation.x = Math.cos(t + Math.PI * 1.5) * Math.PI / 3;
this.pawBL.position.z = -Math.cos(Math.PI + t) * amp;
}
Hero.prototype.jump = function() {
if(this.status == "jumping") return;
this.status = "jumping";
var _this = this;
var totalSpeed = 10 / speed;
var jumpHeight = 45;
TweenMax.to(this.earL.rotation, totalSpeed, {
x: "+=.3",
ease: Back.easeOut
});
TweenMax.to(this.earR.rotation, totalSpeed, {
x: "-=.3",
ease: Back.easeOut
});
TweenMax.to(this.pawFL.rotation, totalSpeed, {
x: "+=.7",
ease: Back.easeOut
});
TweenMax.to(this.pawFR.rotation, totalSpeed, {
x: "-=.7",
ease: Back.easeOut
});
TweenMax.to(this.pawBL.rotation, totalSpeed, {
x: "+=.7",
ease: Back.easeOut
});
TweenMax.to(this.pawBR.rotation, totalSpeed, {
x: "-=.7",
ease: Back.easeOut
});
TweenMax.to(this.tail.rotation, totalSpeed, {
x: "+=1",
ease: Back.easeOut
});
TweenMax.to(this.mouth.rotation, totalSpeed, {
x: .5,
ease: Back.easeOut
});
TweenMax.to(this.mesh.position, totalSpeed / 2, {
y: jumpHeight,
ease: Power2.easeOut
});
TweenMax.to(this.mesh.position, totalSpeed / 2, {
y: 0,
ease: Power4.easeIn,
delay: totalSpeed / 2,
onComplete: function() {
_this.status = "running";
}
});
}
Monster = function() {
this.runningCycle = 0;
this.mesh = new THREE.Group();
this.body = new THREE.Group();
var torsoGeom = new THREE.CubeGeometry(15, 15, 20, 1);
this.torso = new THREE.Mesh(torsoGeom, blackMat);
var headGeom = new THREE.CubeGeometry(20, 20, 40, 1);
headGeom.applyMatrix(new THREE.Matrix4().makeTranslation(0, 0, 20));
this.head = new THREE.Mesh(headGeom, blackMat);
this.head.position.z = 12;
this.head.position.y = 2;
var mouthGeom = new THREE.CubeGeometry(10, 4, 20, 1);
mouthGeom.applyMatrix(new THREE.Matrix4().makeTranslation(0, -2, 10));
this.mouth = new THREE.Mesh(mouthGeom, blackMat);
this.mouth.position.y = -8;
this.mouth.rotation.x = .4;
this.mouth.position.z = 4;
this.heroHolder = new THREE.Group();
this.heroHolder.position.z = 20;
this.mouth.add(this.heroHolder);
var toothGeom = new THREE.CubeGeometry(2, 2, 1, 1);
toothGeom.vertices[1].x -= 1;
toothGeom.vertices[4].x += 1;
toothGeom.vertices[5].x += 1;
toothGeom.vertices[0].x -= 1;
for(var i = 0; i < 3; i++) {
var toothf = new THREE.Mesh(toothGeom, whiteMat);
toothf.position.x = -2.8 + i * 2.5;
toothf.position.y = 1;
toothf.position.z = 19;
var toothl = new THREE.Mesh(toothGeom, whiteMat);
toothl.rotation.y = Math.PI / 2;
toothl.position.z = 12 + i * 2.5;
toothl.position.y = 1;
toothl.position.x = 4;
var toothr = toothl.clone();
toothl.position.x = -4;
this.mouth.add(toothf);
this.mouth.add(toothl);
this.mouth.add(toothr);
}
var tongueGeometry = new THREE.CubeGeometry(6, 1, 14);
tongueGeometry.applyMatrix(new THREE.Matrix4().makeTranslation(0, 0, 7));
this.tongue = new THREE.Mesh(tongueGeometry, pinkMat);
this.tongue.position.z = 2;
this.tongue.rotation.x = -.2;
this.mouth.add(this.tongue);
var noseGeom = new THREE.CubeGeometry(4, 4, 4, 1);
this.nose = new THREE.Mesh(noseGeom, pinkMat);
this.nose.position.z = 39.5;
this.nose.position.y = 9;
this.head.add(this.nose);
this.head.add(this.mouth);
var eyeGeom = new THREE.CubeGeometry(2, 3, 3);
this.eyeL = new THREE.Mesh(eyeGeom, whiteMat);
this.eyeL.position.x = 10;
this.eyeL.position.z = 5;
this.eyeL.position.y = 5;
this.eyeL.castShadow = true;
this.head.add(this.eyeL);
var irisGeom = new THREE.CubeGeometry(.6, 1, 1);
this.iris = new THREE.Mesh(irisGeom, blackMat);
this.iris.position.x = 1.2;
this.iris.position.y = -1;
this.iris.position.z = 1;
this.eyeL.add(this.iris);
this.eyeR = this.eyeL.clone();
this.eyeR.children[0].position.x = -this.iris.position.x;
this.eyeR.position.x = -this.eyeL.position.x;
this.head.add(this.eyeR);
var earGeom = new THREE.CubeGeometry(8, 6, 2, 1);
earGeom.vertices[1].x -= 4;
earGeom.vertices[4].x += 4;
earGeom.vertices[5].x += 4;
earGeom.vertices[5].z -= 2;
earGeom.vertices[0].x -= 4;
earGeom.vertices[0].z -= 2;
earGeom.applyMatrix(new THREE.Matrix4().makeTranslation(0, 3, 0));
this.earL = new THREE.Mesh(earGeom, blackMat);
this.earL.position.x = 6;
this.earL.position.z = 1;
this.earL.position.y = 10;
this.earL.castShadow = true;
this.head.add(this.earL);
this.earR = this.earL.clone();
this.earR.position.x = -this.earL.position.x;
this.earR.rotation.z = -this.earL.rotation.z;
this.head.add(this.earR);
var eyeGeom = new THREE.CubeGeometry(2, 4, 4);
var tailGeom = new THREE.CylinderGeometry(5, 2, 20, 4, 1);
tailGeom.applyMatrix(new THREE.Matrix4().makeTranslation(0, 10, 0));
tailGeom.applyMatrix(new THREE.Matrix4().makeRotationX(-Math.PI / 2));
tailGeom.applyMatrix(new THREE.Matrix4().makeRotationZ(Math.PI / 4));
this.tail = new THREE.Mesh(tailGeom, blackMat);
this.tail.position.z = -10;
this.tail.position.y = 4;
this.torso.add(this.tail);
var pawGeom = new THREE.CylinderGeometry(1.5, 0, 10);
pawGeom.applyMatrix(new THREE.Matrix4().makeTranslation(0, -5, 0));
this.pawFL = new THREE.Mesh(pawGeom, blackMat);
this.pawFL.position.y = -7.5;
this.pawFL.position.z = 8.5;
this.pawFL.position.x = 5.5;
this.torso.add(this.pawFL);
this.pawFR = this.pawFL.clone();
this.pawFR.position.x = -this.pawFL.position.x;
this.torso.add(this.pawFR);
this.pawBR = this.pawFR.clone();
this.pawBR.position.z = -this.pawFL.position.z;
this.torso.add(this.pawBR);
this.pawBL = this.pawBR.clone();
this.pawBL.position.x = this.pawFL.position.x;
this.torso.add(this.pawBL);
this.mesh.add(this.body);
this.torso.add(this.head);
this.body.add(this.torso);
this.torso.castShadow = true;
this.head.castShadow = true;
this.pawFL.castShadow = true;
this.pawFR.castShadow = true;
this.pawBL.castShadow = true;
this.pawBR.castShadow = true;
this.body.rotation.y = Math.PI / 2;
}
Monster.prototype.run = function() {
var s = Math.min(speed, maxSpeed);
this.runningCycle += delta * s * .7;
this.runningCycle = this.runningCycle % (Math.PI * 2);
var t = this.runningCycle;
this.pawFR.rotation.x = Math.sin(t) * Math.PI / 4;
this.pawFR.position.y = -5.5 - Math.sin(t);
this.pawFR.position.z = 7.5 + Math.cos(t);
this.pawFL.rotation.x = Math.sin(t + .4) * Math.PI / 4;
this.pawFL.position.y = -5.5 - Math.sin(t + .4);
this.pawFL.position.z = 7.5 + Math.cos(t + .4);
this.pawBL.rotation.x = Math.sin(t + 2) * Math.PI / 4;
this.pawBL.position.y = -5.5 - Math.sin(t + 3.8);
this.pawBL.position.z = -7.5 + Math.cos(t + 3.8);
this.pawBR.rotation.x = Math.sin(t + 2.4) * Math.PI / 4;
this.pawBR.position.y = -5.5 - Math.sin(t + 3.4);
this.pawBR.position.z = -7.5 + Math.cos(t + 3.4);
this.torso.rotation.x = Math.sin(t) * Math.PI / 8;
this.torso.position.y = 3 - Math.sin(t + Math.PI / 2) * 3;
this.head.rotation.x = -.1 + Math.sin(-t - 1) * .4;
this.mouth.rotation.x = .2 + Math.sin(t + Math.PI + .3) * .4;
this.tail.rotation.x = .2 + Math.sin(t - Math.PI / 2);
this.eyeR.scale.y = .5 + Math.sin(t + Math.PI) * .5;
}
Hero.prototype.nod = function() {
var _this = this;
var sp = .5 + Math.random();
// 头
var tHeadRotY = -Math.PI / 6 + Math.random() * Math.PI / 3;
TweenMax.to(this.head.rotation, sp, {
y: tHeadRotY,
ease: Power4.easeInOut,
onComplete: function() {
_this.nod()
}
});
// 耳朵
var tEarLRotX = Math.PI / 4 + Math.random() * Math.PI / 6;
var tEarRRotX = Math.PI / 4 + Math.random() * Math.PI / 6;
TweenMax.to(this.earL.rotation, sp, {
x: tEarLRotX,
ease: Power4.easeInOut
});
TweenMax.to(this.earR.rotation, sp, {
x: tEarRRotX,
ease: Power4.easeInOut
});
// PAWS BACK LEFT
var tPawBLRot = Math.random() * Math.PI / 2;
var tPawBLY = -4 + Math.random() * 8;
TweenMax.to(this.pawBL.rotation, sp / 2, {
x: tPawBLRot,
ease: Power1.easeInOut,
yoyo: true,
repeat: 2
});
TweenMax.to(this.pawBL.position, sp / 2, {
y: tPawBLY,
ease: Power1.easeInOut,
yoyo: true,
repeat: 2
});
// PAWS BACK RIGHT
var tPawBRRot = Math.random() * Math.PI / 2;
var tPawBRY = -4 + Math.random() * 8;
TweenMax.to(this.pawBR.rotation, sp / 2, {
x: tPawBRRot,
ease: Power1.easeInOut,
yoyo: true,
repeat: 2
});
TweenMax.to(this.pawBR.position, sp / 2, {
y: tPawBRY,
ease: Power1.easeInOut,
yoyo: true,
repeat: 2
});
// 爪子前左
var tPawFLRot = Math.random() * Math.PI / 2;
var tPawFLY = -4 + Math.random() * 8;
TweenMax.to(this.pawFL.rotation, sp / 2, {
x: tPawFLRot,
ease: Power1.easeInOut,
yoyo: true,
repeat: 2
});
TweenMax.to(this.pawFL.position, sp / 2, {
y: tPawFLY,
ease: Power1.easeInOut,
yoyo: true,
repeat: 2
});
// 爪子前右
var tPawFRRot = Math.random() * Math.PI / 2;
var tPawFRY = -4 + Math.random() * 8;
TweenMax.to(this.pawFR.rotation, sp / 2, {
x: tPawFRRot,
ease: Power1.easeInOut,
yoyo: true,
repeat: 2
});
TweenMax.to(this.pawFR.position, sp / 2, {
y: tPawFRY,
ease: Power1.easeInOut,
yoyo: true,
repeat: 2
});
// 口
var tMouthRot = Math.random() * Math.PI / 8;
TweenMax.to(this.mouth.rotation, sp, {
x: tMouthRot,
ease: Power1.easeInOut
});
// IRIS
var tIrisY = -1 + Math.random() * 2;
var tIrisZ = -1 + Math.random() * 2;
var iris1 = this.iris;
var iris2 = this.eyeR.children[0];
TweenMax.to([iris1.position, iris2.position], sp, {
y: tIrisY,
z: tIrisZ,
ease: Power1.easeInOut
});
//眼睛
if(Math.random() > .2) TweenMax.to([this.eyeR.scale, this.eyeL.scale], sp / 8, {
y: 0,
ease: Power1.easeInOut,
yoyo: true,
repeat: 1
});
}
Hero.prototype.hang = function() {
var _this = this;
var sp = 1;
var ease = Power4.easeOut;
TweenMax.killTweensOf(this.eyeL.scale);
TweenMax.killTweensOf(this.eyeR.scale);
this.body.rotation.x = 0;
this.torso.rotation.x = 0;
this.body.position.y = 0;
this.torso.position.y = 7;
TweenMax.to(this.mesh.rotation, sp, {
y: 0,
ease: ease
});
TweenMax.to(this.mesh.position, sp, {
y: -7,
z: 6,
ease: ease
});
TweenMax.to(this.head.rotation, sp, {
x: Math.PI / 6,
ease: ease,
onComplete: function() {
_this.nod();
}
});
TweenMax.to(this.earL.rotation, sp, {
x: Math.PI / 3,
ease: ease
});
TweenMax.to(this.earR.rotation, sp, {
x: Math.PI / 3,
ease: ease
});
TweenMax.to(this.pawFL.position, sp, {
y: -1,
z: 3,
ease: ease
});
TweenMax.to(this.pawFR.position, sp, {
y: -1,
z: 3,
ease: ease
});
TweenMax.to(this.pawBL.position, sp, {
y: -2,
z: -3,
ease: ease
});
TweenMax.to(this.pawBR.position, sp, {
y: -2,
z: -3,
ease: ease
});
TweenMax.to(this.eyeL.scale, sp, {
y: 1,
ease: ease
});
TweenMax.to(this.eyeR.scale, sp, {
y: 1,
ease: ease
});
}
Monster.prototype.nod = function() {
var _this = this;
var sp = 1 + Math.random() * 2;
// HEAD
var tHeadRotY = -Math.PI / 3 + Math.random() * .5;
var tHeadRotX = Math.PI / 3 - .2 + Math.random() * .4;
TweenMax.to(this.head.rotation, sp, {
x: tHeadRotX,
y: tHeadRotY,
ease: Power4.easeInOut,
onComplete: function() {
_this.nod()
}
});
// TAIL
var tTailRotY = -Math.PI / 4;
TweenMax.to(this.tail.rotation, sp / 8, {
y: tTailRotY,
ease: Power1.easeInOut,
yoyo: true,
repeat: 8
});
// EYES
TweenMax.to([this.eyeR.scale, this.eyeL.scale], sp / 20, {
y: 0,
ease: Power1.easeInOut,
yoyo: true,
repeat: 1
});
}
Monster.prototype.sit = function() {
var sp = 1.2;
var ease = Power4.easeOut;
var _this = this;
TweenMax.to(this.torso.rotation, sp, {
x: -1.3,
ease: ease
});
TweenMax.to(this.torso.position, sp, {
y: -5,
ease: ease,
onComplete: function() {
_this.nod();
gameStatus = "readyToReplay";
}
});
TweenMax.to(this.head.rotation, sp, {
x: Math.PI / 3,
y: -Math.PI / 3,
ease: ease
});
TweenMax.to(this.tail.rotation, sp, {
x: 2,
y: Math.PI / 4,
ease: ease
});
TweenMax.to(this.pawBL.rotation, sp, {
x: -.1,
ease: ease
});
TweenMax.to(this.pawBR.rotation, sp, {
x: -.1,
ease: ease
});
TweenMax.to(this.pawFL.rotation, sp, {
x: 1,
ease: ease
});
TweenMax.to(this.pawFR.rotation, sp, {
x: 1,
ease: ease
});
TweenMax.to(this.mouth.rotation, sp, {
x: .3,
ease: ease
});
TweenMax.to(this.eyeL.scale, sp, {
y: 1,
ease: ease
});
TweenMax.to(this.eyeR.scale, sp, {
y: 1,
ease: ease
});
}
Carrot = function() {
this.angle = 0;
this.mesh = new THREE.Group();
var bodyGeom = new THREE.CylinderGeometry(5, 3, 10, 4, 1);
bodyGeom.vertices[8].y += 2;
bodyGeom.vertices[9].y -= 3;
this.body = new THREE.Mesh(bodyGeom, pinkMat);
var leafGeom = new THREE.CubeGeometry(5, 10, 1, 1);
leafGeom.applyMatrix(new THREE.Matrix4().makeTranslation(0, 5, 0));
leafGeom.vertices[2].x -= 1;
leafGeom.vertices[3].x -= 1;
leafGeom.vertices[6].x += 1;
leafGeom.vertices[7].x += 1;
this.leaf1 = new THREE.Mesh(leafGeom, greenMat);
this.leaf1.position.y = 7;
this.leaf1.rotation.z = .3;
this.leaf1.rotation.x = .2;
this.leaf2 = this.leaf1.clone();
this.leaf2.scale.set(1, 1.3, 1);
this.leaf2.position.y = 7;
this.leaf2.rotation.z = -.3;
this.leaf2.rotation.x = -.2;
this.mesh.add(this.body);
this.mesh.add(this.leaf1);
this.mesh.add(this.leaf2);
this.body.traverse(function(object) {
if(object instanceof THREE.Mesh) {
object.castShadow = true;
object.receiveShadow = true;
}
});
}
Hedgehog = function() {
this.angle = 0;
this.status = "ready";
this.mesh = new THREE.Group();
var bodyGeom = new THREE.CubeGeometry(6, 6, 6, 1);
this.body = new THREE.Mesh(bodyGeom, blackMat);
var headGeom = new THREE.CubeGeometry(5, 5, 7, 1);
this.head = new THREE.Mesh(headGeom, lightBrownMat);
this.head.position.z = 6;
this.head.position.y = -.5;
var noseGeom = new THREE.CubeGeometry(1.5, 1.5, 1.5, 1);
this.nose = new THREE.Mesh(noseGeom, blackMat);
this.nose.position.z = 4;
this.nose.position.y = 2;
var eyeGeom = new THREE.CubeGeometry(1, 3, 3);
this.eyeL = new THREE.Mesh(eyeGeom, whiteMat);
this.eyeL.position.x = 2.2;
this.eyeL.position.z = -.5;
this.eyeL.position.y = .8;
this.eyeL.castShadow = true;
this.head.add(this.eyeL);
var irisGeom = new THREE.CubeGeometry(.5, 1, 1);
this.iris = new THREE.Mesh(irisGeom, blackMat);
this.iris.position.x = .5;
this.iris.position.y = .8;
this.iris.position.z = .8;
this.eyeL.add(this.iris);
this.eyeR = this.eyeL.clone();
this.eyeR.children[0].position.x = -this.iris.position.x;
this.eyeR.position.x = -this.eyeL.position.x;
var spikeGeom = new THREE.CubeGeometry(.5, 2, .5, 1);
spikeGeom.applyMatrix(new THREE.Matrix4().makeTranslation(0, 1, 0));
for(var i = 0; i < 9; i++) {
var row = (i % 3);
var col = Math.floor(i / 3);
var sb = new THREE.Mesh(spikeGeom, blackMat);
sb.rotation.x = -Math.PI / 2 + (Math.PI / 12 * row) - .5 + Math.random();
sb.position.z = -3;
sb.position.y = -2 + row * 2;
sb.position.x = -2 + col * 2;
this.body.add(sb);
var st = new THREE.Mesh(spikeGeom, blackMat);
st.position.y = 3;
st.position.x = -2 + row * 2;
st.position.z = -2 + col * 2;
st.rotation.z = Math.PI / 6 - (Math.PI / 6 * row) - .5 + Math.random();
this.body.add(st);
var sr = new THREE.Mesh(spikeGeom, blackMat);
sr.position.x = 3;
sr.position.y = -2 + row * 2;
sr.position.z = -2 + col * 2;
sr.rotation.z = -Math.PI / 2 + (Math.PI / 12 * row) - .5 + Math.random();
this.body.add(sr);
var sl = new THREE.Mesh(spikeGeom, blackMat);
sl.position.x = -3;
sl.position.y = -2 + row * 2;
sl.position.z = -2 + col * 2;
sl.rotation.z = Math.PI / 2 - (Math.PI / 12 * row) - .5 + Math.random();;
this.body.add(sl);
}
this.head.add(this.eyeR);
var earGeom = new THREE.CubeGeometry(2, 2, .5, 1);
this.earL = new THREE.Mesh(earGeom, lightBrownMat);
this.earL.position.x = 2.5;
this.earL.position.z = -2.5;
this.earL.position.y = 2.5;
this.earL.rotation.z = -Math.PI / 12;
this.earL.castShadow = true;
this.head.add(this.earL);
this.earR = this.earL.clone();
this.earR.position.x = -this.earL.position.x;
this.earR.rotation.z = -this.earL.rotation.z;
this.earR.castShadow = true;
this.head.add(this.earR);
var mouthGeom = new THREE.CubeGeometry(1, 1, .5, 1);
this.mouth = new THREE.Mesh(mouthGeom, blackMat);
this.mouth.position.z = 3.5;
this.mouth.position.y = -1.5;
this.head.add(this.mouth);
this.mesh.add(this.body);
this.body.add(this.head);
this.head.add(this.nose);
this.mesh.traverse(function(object) {
if(object instanceof THREE.Mesh) {
object.castShadow = true;
object.receiveShadow = true;
}
});
}
Hedgehog.prototype.nod = function() {
var _this = this;
var speed = .1 + Math.random() * .5;
var angle = -Math.PI / 4 + Math.random() * Math.PI / 2;
TweenMax.to(this.head.rotation, speed, {
y: angle,
onComplete: function() {
_this.nod();
}
});
}
function createHero() {
hero = new Hero();
hero.mesh.rotation.y = Math.PI / 2;
scene.add(hero.mesh);
hero.nod();
}
function createMonster() {
monster = new Monster();
monster.mesh.position.z = 20;
scene.add(monster.mesh);
updateMonsterPosition();
}
function updateMonsterPosition() {
monster.run();
monsterPosTarget -= delta * monsterAcceleration;
monsterPos += (monsterPosTarget - monsterPos) * delta;
if(monsterPos < .56) {
gameOver();
}
var angle = Math.PI * monsterPos;
monster.mesh.position.y = -floorRadius + Math.sin(angle) * (floorRadius + 12);
monster.mesh.position.x = Math.cos(angle) * (floorRadius + 15);
monster.mesh.rotation.z = -Math.PI / 2 + angle;
}
function gameOver() {
fieldGameOver.className = "show";
gameStatus = "gameOver";
monster.sit();
hero.hang();
monster.heroHolder.add(hero.mesh);
TweenMax.to(this, 1, {
speed: 0
});
TweenMax.to(camera.position, 3, {
z: cameraPosGameOver,
y: 60,
x: -30
});
carrot.mesh.visible = false;
obstacle.mesh.visible = false;
clearInterval(levelInterval);
}
function replay() {
gameStatus = "preparingToReplay"
fieldGameOver.className = "";
TweenMax.killTweensOf(monster.pawFL.position);
TweenMax.killTweensOf(monster.pawFR.position);
TweenMax.killTweensOf(monster.pawBL.position);
TweenMax.killTweensOf(monster.pawBR.position);
TweenMax.killTweensOf(monster.pawFL.rotation);
TweenMax.killTweensOf(monster.pawFR.rotation);
TweenMax.killTweensOf(monster.pawBL.rotation);
TweenMax.killTweensOf(monster.pawBR.rotation);
TweenMax.killTweensOf(monster.tail.rotation);
TweenMax.killTweensOf(monster.head.rotation);
TweenMax.killTweensOf(monster.eyeL.scale);
TweenMax.killTweensOf(monster.eyeR.scale);
monster.tail.rotation.y = 0;
TweenMax.to(camera.position, 3, {
z: cameraPosGame,
x: 0,
y: 30,
ease: Power4.easeInOut
});
TweenMax.to(monster.torso.rotation, 2, {
x: 0,
ease: Power4.easeInOut
});
TweenMax.to(monster.torso.position, 2, {
y: 0,
ease: Power4.easeInOut
});
TweenMax.to(monster.pawFL.rotation, 2, {
x: 0,
ease: Power4.easeInOut
});
TweenMax.to(monster.pawFR.rotation, 2, {
x: 0,
ease: Power4.easeInOut
});
TweenMax.to(monster.mouth.rotation, 2, {
x: .5,
ease: Power4.easeInOut
});
TweenMax.to(monster.head.rotation, 2, {
y: 0,
x: -.3,
ease: Power4.easeInOut
});
TweenMax.to(hero.mesh.position, 2, {
x: 20,
ease: Power4.easeInOut
});
TweenMax.to(hero.head.rotation, 2, {
x: 0,
y: 0,
ease: Power4.easeInOut
});
TweenMax.to(monster.mouth.rotation, 2, {
x: .2,
ease: Power4.easeInOut
});
TweenMax.to(monster.mouth.rotation, 1, {
x: .4,
ease: Power4.easeIn,
delay: 1,
onComplete: function() {
resetGame();
}
});
}
Fir = function() {
var height = 200;
var truncGeom = new THREE.CylinderGeometry(2, 2, height, 6, 1);
truncGeom.applyMatrix(new THREE.Matrix4().makeTranslation(0, height / 2, 0));
this.mesh = new THREE.Mesh(truncGeom, greenMat);
this.mesh.castShadow = true;
}
var firs = new THREE.Group();
function createFirs() {
var nTrees = 100;
for(var i = 0; i < nTrees; i++) {
var phi = i * (Math.PI * 2) / nTrees;
var theta = Math.PI / 2;
theta += (Math.random() > .05) ? .25 + Math.random() * .3 : -.35 - Math.random() * .1;
var fir = new Tree();
fir.mesh.position.x = Math.sin(theta) * Math.cos(phi) * floorRadius;
fir.mesh.position.y = Math.sin(theta) * Math.sin(phi) * (floorRadius - 10);
fir.mesh.position.z = Math.cos(theta) * floorRadius;
var vec = fir.mesh.position.clone();
var axis = new THREE.Vector3(0, 1, 0);
fir.mesh.quaternion.setFromUnitVectors(axis, vec.clone().normalize());
floor.add(fir.mesh);
}
}
function createCarrot() {
carrot = new Carrot();
scene.add(carrot.mesh);
}
function updateCarrotPosition() {
carrot.mesh.rotation.y += delta * 6;
carrot.mesh.rotation.z = Math.PI / 2 - (floorRotation + carrot.angle);
carrot.mesh.position.y = -floorRadius + Math.sin(floorRotation + carrot.angle) * (floorRadius + 50);
carrot.mesh.position.x = Math.cos(floorRotation + carrot.angle) * (floorRadius + 50);
}
function updateObstaclePosition() {
if(obstacle.status == "flying") return;
if(floorRotation + obstacle.angle > 2.5) {
obstacle.angle = -floorRotation + Math.random() * .3;
obstacle.body.rotation.y = Math.random() * Math.PI * 2;
}
obstacle.mesh.rotation.z = floorRotation + obstacle.angle - Math.PI / 2;
obstacle.mesh.position.y = -floorRadius + Math.sin(floorRotation + obstacle.angle) * (floorRadius + 3);
obstacle.mesh.position.x = Math.cos(floorRotation + obstacle.angle) * (floorRadius + 3);
}
function updateFloorRotation() {
floorRotation += delta * .03 * speed;
floorRotation = floorRotation % (Math.PI * 2);
floor.rotation.z = floorRotation;
}
function createObstacle() {
obstacle = new Hedgehog();
obstacle.body.rotation.y = -Math.PI / 2;
obstacle.mesh.scale.set(1.1, 1.1, 1.1);
obstacle.mesh.position.y = floorRadius + 4;
obstacle.nod();
scene.add(obstacle.mesh);
}
function createBonusParticles() {
bonusParticles = new BonusParticles();
bonusParticles.mesh.visible = false;
scene.add(bonusParticles.mesh);
}
function checkCollision() {
var db = hero.mesh.position.clone().sub(carrot.mesh.position.clone());
var dm = hero.mesh.position.clone().sub(obstacle.mesh.position.clone());
if(db.length() < collisionBonus) {
getBonus();
}
if(dm.length() < collisionObstacle && obstacle.status != "flying") {
getMalus();
}
}
function getBonus() {
bonusParticles.mesh.position.copy(carrot.mesh.position);
bonusParticles.mesh.visible = true;
bonusParticles.explose();
carrot.angle += Math.PI / 2;
monsterPosTarget += .025;
}
function getMalus() {
obstacle.status = "flying";
var tx = (Math.random() > .5) ? -20 - Math.random() * 10 : 20 + Math.random() * 5;
TweenMax.to(obstacle.mesh.position, 4, {
x: tx,
y: Math.random() * 50,
z: 350,
ease: Power4.easeOut
});
TweenMax.to(obstacle.mesh.rotation, 4, {
x: Math.PI * 3,
z: Math.PI * 3,
y: Math.PI * 6,
ease: Power4.easeOut,
onComplete: function() {
obstacle.status = "ready";
obstacle.body.rotation.y = Math.random() * Math.PI * 2;
obstacle.angle = -floorRotation - Math.random() * .4;
obstacle.angle = obstacle.angle % (Math.PI * 2);
obstacle.mesh.rotation.x = 0;
obstacle.mesh.rotation.y = 0;
obstacle.mesh.rotation.z = 0;
obstacle.mesh.position.z = 0;
}
});
monsterPosTarget -= .04;
TweenMax.from(this, .5, {
malusClearAlpha: .5,
onUpdate: function() {
renderer.setClearColor(malusClearColor, malusClearAlpha);
}
})
}
function updateDistance() {
distance += delta * speed;
var d = distance / 2;
fieldDistance.innerHTML = Math.floor(d);
}
function updateLevel() {
if(speed >= maxSpeed) return;
level++;
speed += 2;
}
function loop() {
delta = clock.getDelta();
updateFloorRotation();
if(gameStatus == "play") {
if(hero.status == "running") {
hero.run();
}
updateDistance();
updateMonsterPosition();
updateCarrotPosition();
updateObstaclePosition();
checkCollision();
}
render();
requestAnimationFrame(loop);
}
function render() {
renderer.render(scene, camera);
}
window.addEventListener('load', init, false);
function init(event) {
initScreenAnd3D();
createLights();
createFloor()
createHero();
createMonster();
createFirs();
createCarrot();
createBonusParticles();
createObstacle();
initUI();
resetGame();
loop();
}
function resetGame() {
scene.add(hero.mesh);
hero.mesh.rotation.y = Math.PI / 2;
hero.mesh.position.y = 0;
hero.mesh.position.z = 0;
hero.mesh.position.x = 0;
monsterPos = .56;
monsterPosTarget = .65;
speed = initSpeed;
level = 0;
distance = 0;
carrot.mesh.visible = true;
obstacle.mesh.visible = true;
gameStatus = "play";
hero.status = "running";
hero.nod();
audio.play();
updateLevel();
levelInterval = setInterval(updateLevel, levelUpdateFreq);
}
function initUI() {
fieldDistance = document.getElementById("distValue");
fieldGameOver = document.getElementById("gameoverInstructions");
}
//模型
// 树
Tree = function() {
this.mesh = new THREE.Object3D();
this.trunc = new Trunc();
this.mesh.add(this.trunc.mesh);
}
Trunc = function() {
var truncHeight = 50 + Math.random() * 150;
var topRadius = 1 + Math.random() * 5;
var bottomRadius = 5 + Math.random() * 5;
var mats = [blackMat, brownMat, pinkMat, whiteMat, greenMat, lightBrownMat, pinkMat];
var matTrunc = blackMat;
var nhSegments = 3;
var nvSegments = 3;
var geom = new THREE.CylinderGeometry(topRadius, bottomRadius, truncHeight, nhSegments, nvSegments);
geom.applyMatrix(new THREE.Matrix4().makeTranslation(0, truncHeight / 2, 0));
this.mesh = new THREE.Mesh(geom, matTrunc);
for(var i = 0; i < geom.vertices.length; i++) {
var noise = Math.random();
var v = geom.vertices[i];
v.x += -noise + Math.random() * noise * 2;
v.y += -noise + Math.random() * noise * 2;
v.z += -noise + Math.random() * noise * 2;
geom.computeVertexNormals();
// 水果
if(Math.random() > .7) {
var size = Math.random() * 3;
var fruitGeometry = new THREE.CubeGeometry(size, size, size, 1);
var matFruit = mats[Math.floor(Math.random() * mats.length)];
var fruit = new THREE.Mesh(fruitGeometry, matFruit);
fruit.position.x = v.x;
fruit.position.y = v.y + 3;
fruit.position.z = v.z;
fruit.rotation.x = Math.random() * Math.PI;
fruit.rotation.y = Math.random() * Math.PI;
this.mesh.add(fruit);
}
// 树枝
if(Math.random() > .5 && v.y > 10 && v.y < truncHeight - 10) {
var h = 3 + Math.random() * 5;
var thickness = .2 + Math.random();
var branchGeometry = new THREE.CylinderGeometry(thickness / 2, thickness, h, 3, 1);
branchGeometry.applyMatrix(new THREE.Matrix4().makeTranslation(0, h / 2, 0));
var branch = new THREE.Mesh(branchGeometry, matTrunc);
branch.position.x = v.x;
branch.position.y = v.y;
branch.position.z = v.z;
var vec = new THREE.Vector3(v.x, 2, v.z);
var axis = new THREE.Vector3(0, 1, 0);
branch.quaternion.setFromUnitVectors(axis, vec.clone().normalize());
this.mesh.add(branch);
}
}
this.mesh.castShadow = true;
}
</script>
<style class="cp-pen-styles">
html,
body {
margin: 0;
padding: 0;
}
#world {
position: absolute;
width: 100%;
height: 100%;
background-color: #dbe6e6;
overflow: hidden;
}
#gameoverInstructions {
position: absolute;
font-family: 'Voltaire', sans-serif;
font-weight: bold;
text-transform: uppercase;
font-size: 120px;
text-align: center;
color: #ffc5a2;
opacity: 0;
left: 50%;
top: 50%;
width: 100%;
-webkit-transform: translate(-50%, -100%);
transform: translate(-50%, -100%);
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-transition: all 500ms ease-in-out;
transition: all 500ms ease-in-out;
}
#gameoverInstructions.show {
opacity: 1;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
-webkit-transition: all 500ms ease-in-out;
transition: all 500ms ease-in-out;
}
#dist {
position: absolute;
left: 50%;
top: 50px;
-webkit-transform: translate(-50%, 0%);
transform: translate(-50%, 0%);
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.label {
position: relative;
font-family: 'Voltaire', sans-serif;
text-transform: uppercase;
color: #ffa873;
font-size: 12px;
letter-spacing: 2px;
text-align: center;
margin-bottom: 5px;
}
#distValue {
position: relative;
text-transform: uppercase;
color: #dc5f45;
font-size: 40px;
font-family: 'Voltaire';
text-align: center;
}
#distValue:after {
content: "M";
font-size: 20px;
}
#credits {
position: absolute;
width: 100%;
margin: auto;
bottom: 0;
margin-bottom: 20px;
font-family: 'Voltaire', sans-serif;
color: #544027;
font-size: 12px;
letter-spacing: 0.5px;
text-transform: uppercase;
text-align: center;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
#credits a {
color: #544027;
}
#credits a:hover {
color: #dc5f45;
}
#instructions {
position: absolute;
width: 100%;
bottom: 0;
margin: auto;
margin-bottom: 50px;
font-family: 'Voltaire', sans-serif;
color: #dc5f45;
font-size: 16px;
letter-spacing: 1px;
text-transform: uppercase;
text-align: center;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.lightInstructions {
color: #5f9042;
}
</style>
</head>
<body>
<div id="world" />
<div id="gameoverInstructions">
Game Over
</div>
<div id="dist">
<div class="label">距离</div>
<div id="distValue">0</div>
</div>
<div id="instructions">点击跳跃<span class="lightInstructions"> — 抓住胡萝卜,避开刺猬</span></div>
<div id="credits">
<p>
<a href="https://epic.net" target="blank">作者:epic.net</a>
<a target="_blank" href="http://shang.qq.com/wpa/qunwpa?idkey=c482bc366efa0cca2340c3410082ffcee032589eabc0feaf07231787fe425576">
整理:Q群170931289(点击加入)
</a>
</p>
</div>
</body>
</html>
流量监控背景
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>流量监控背景</title>
</head>
<body style="overflow-x:hidden;">
<canvas id="canvas" ></canvas>
</body>
<script>
canvas = document.getElementById('canvas');
ctx = canvas.getContext('2d');
//宽高可自行设置
w = canvas.width = window.innerWidth;
h = canvas.height = window.innerHeight-50;
hue = 217;
stars = [];
count = 0,
//设置星星数量
maxStars = 1500;
canvas2 = document.createElement('canvas');
w2 = canvas2.width = 100;
h2 = canvas2.height = 100;
ctx2 = canvas2.getContext("2d");
gradientCache = ctx2.createRadialGradient(w2 / 2, h2 / 2, 0, w2 / 2,
h2 / 2, w2 / 2);
gradientCache.addColorStop(0.025, '#fff');
gradientCache.addColorStop(0.1, 'hsl(' + hue + ', 61%, 33%)');
gradientCache.addColorStop(0.25, 'hsl(' + hue + ', 64%, 6%)');
gradientCache.addColorStop(1, 'transparent');
ctx2.fillStyle = gradientCache;
ctx2.beginPath();
ctx2.arc(w2 / 2, h2 / 2, w2 / 2, 0, Math.PI * 2);
ctx2.fill();
function random(min, max) {
if (arguments.length < 2) {
max = min;
min = 0;
}
if (min > max) {
var hold = max;
max = min;
min = hold;
}
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function maxOrbit(x, y) {
var max = Math.max(x, y), diameter = Math.round(Math.sqrt(max * max
+ max * max));
return diameter / 2;
}
Star = function() {
this.orbitRadius = random(maxOrbit(w, h));
this.radius = random(60, this.orbitRadius) / 10;
this.orbitX = w / 2;
this.orbitY = h / 2;
this.timePassed = random(2, maxStars);
this.speed = random(this.orbitRadius) / 120000;//设置旋转速度,数值越小速度越快
this.alpha = random(2, 10) / 10;
count++;
stars[count] = this;
}
Star.prototype.draw = function() {
x = Math.sin(this.timePassed) * this.orbitRadius + this.orbitX,
y = Math.cos(this.timePassed) * this.orbitRadius
+ this.orbitY, twinkle = random(10);
if (twinkle === 1 && this.alpha > 0) {
this.alpha -= 0.05;
} else if (twinkle === 2 && this.alpha < 1) {
this.alpha += 0.05;
}
ctx.globalAlpha = this.alpha;
ctx.drawImage(canvas2, x - this.radius / 2, y - this.radius / 2,
this.radius, this.radius);
this.timePassed += this.speed;
}
for (var i = 0; i < maxStars; i++) {
new Star();
}
function start() {
ctx.globalCompositeOperation = 'source-over';
ctx.globalAlpha = 1;
ctx.fillStyle = 'hsla(' + hue + ', 64%,6%,0.2)';//最后小数设置星轨残影,数值越大残影越小
ctx.fillRect(0, 0, w, h)
ctx.globalCompositeOperation = 'lighter';
for (var i = 1, l = stars.length; i < l; i++) {
stars[i].draw();
}
;
window.requestAnimationFrame(start);
}
start();
</script>
</html>