H5实现魔方游戏
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WebGL魔方小游戏 - www.web-tinker.com</title>
<style>* {padding:0px;margin:0px;overflow:hidden;background:#000;}</style>
<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>
<base href="http://www.web-tinker.com/files/" />
<script src="SimpleWebGL.2.0.js"></script>
<script src="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>
</head>
<body>
</body>
</html>
H5实现魔方游戏的更多相关文章
- 亲历H5移动端游戏微信支付接入及那些坑(二)——获取Openid和授权
第一篇中将一些坑说明,那么这篇开始正式进入接入步骤.具体的参数说明,我不会列出,毕竟微信官方文档都有,我想大家都看的懂,而且这接口也有可能微信会变动,所以不列出来,也是不想引起大家的误解,接入步骤只起 ...
- 【c#】仅1600行代码 2D魔方游戏源码-纯WinForm
想起以前高三的时候写过一个很无脑的程序,那个时候.net5.0都还没影儿呢,,现在分享一下.一个平面展开的魔方游戏. 这个是1.0版本,有些许bug. 比如左边的格子操作不了. 「2d cube.ex ...
- H5版定点投篮游戏(1)--物理模型抽象
前言: 前几天目睹了大学同学开了个微店, 算是间接体验微信公众平台的使用. 觉得非常便捷和方便, 于是自己也想捣鼓一个. 公众号取名: "木目的H5游戏世界", 定位做成一个, 个 ...
- 亲历H5移动端游戏微信支付接入及那些坑(一)——支付方式与坑
最近项目进入中后期,开始接入支付.要求是使用微信支付,呵呵,好笑的是不知老板从哪里听来的,居然和我说只要是熟手,接个微信支付两小时搞定,我只能再次呵呵.先不说支付处理逻辑,而且公司本来也没现成的接入模 ...
- 3D魔方游戏
初学OpenGL时做的小程序,涉及到了OpenGL的大部分基本内容,如视图模型变换.色彩.纹理贴图.材质.光照.显示列表.选择等 三阶魔方有3×3×3个方块组成,每个方块的类当中都有一个4×4的矩阵, ...
- 抖音圈圈乐 系统搭建H5微信小游戏圈圈乐系统介绍
网红线下游戏抖音圈圈乐改造而来 一.搭建此系统需要准备如下资料: 1. 认证微信服务号 2. 微信支付商户号 3. 备案域名及云服务器 二.系统功能简介: 1. 游戏闯关 2. 每个商品闯关难度后台自 ...
- 亲历H5移动端游戏微信支付接入及那些坑(四)——参考文档
写完三篇后,我觉得微信支付的文档确实比较乱,所以在此做一个整理汇总 支付流程相关文档 一下文档已经按照接入顺序排列,请依次参考阅读 微信公众号网页授权两种access_token区别,获取用户open ...
- 以前做的H5推广小游戏(活动及派发奖品形式)
润百颜 1 微信授权登录,获取用户openid.一个openid一次抽奖机会,该openid用户多次玩游戏抽奖,仍然是相同的优惠码. 2 游戏结束抽奖,100%中奖,获得优惠码.优惠码和openid保 ...
- 亲历H5移动端游戏微信支付接入及那些坑(三)——支付接入
终于到接入支付了,小小的一个微信支付,居然也写了3篇,好长,好累. 接入环境 对接入环境,前端的话,应该是以js为主吧,也有可能是,PHP,Java,C++,或者C#都可以.为什么在此特意提一下接入环 ...
随机推荐
- ssm中通过ajax或jquer的validate验证原密码与修改密码的正确性
一.ajax 1. <script type="text/javascript"> //验证原密码1.ajax,正则 var ok1=false,ok2=false,o ...
- Beta冲刺 (1/7)
Part.1 开篇 队名:彳艮彳亍团队 组长博客:戳我进入 作业博客:班级博客本次作业的链接 Part.2 成员汇报 组员1(组长)柯奇豪 过去两天完成了哪些任务 熟悉并编写小程序的自定义控件 展示G ...
- EF6 学习笔记(一):Code First 方式生成数据库及初始化数据库实际操作
EF6 学习笔记总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 本篇参考原文地址: Creating an Entity Framework Data Model 说明:学习 ...
- Vuejs——(1)入门(单向绑定、双向绑定、列表渲染、响应函数)
版权声明:出处http://blog.csdn.net/qq20004604 目录(?)[+] 参照链接: http://cn.vuejs.org/guide/index.html [起步]部 ...
- ReactNative学习笔记(五)踩坑总结
已经发现的bug或者问题 Android不支持shadow属性: Animated.Image的borderRadius不生效: setNativeProps无法修改图片的source: 没有直接设置 ...
- 4.ASP.NET MVC 5.0 视图之模型绑定
大家好,这篇文章,我将向大家介绍ASP.NET MVC的模型视图绑定,ASP.MVC的模型绑定分为两种:一种是动态绑定[Dynamic Binding];还有一种就是强类型绑定[Strongly ty ...
- 迁移桌面程序到MS Store(1)——通过Visual Studio创建Packaging工程
之前跑去做了一年多的iOS开发,被XCode恶心得不行.做人呢,最重要的是开心.所以我就炒了公司鱿鱼,挪了个窝回头去做Windows开发了. UWP什么的很久没有正儿八经写了,国内的需求 ...
- JQuery下载及选择器总结
JQuery下载 JQuery只是一个JS函数库,要使用其中的方法还是要在JS文件中进行调用. 一般去https://mvnrepository.com/这个网站下载,搜索JQuery就能找到JS文件 ...
- 玩玩vs Git 中国版 Gitee
下载vs 下载 Gitee.VisualStudio.vsix https://gitee.com/GitGroup/CodeCloud.VisualStudio/attach_files 去git ...
- Android热修复——Tinker的集成
前言 做前端开发的都知道,当我们项目做完了以后,都会把应用上传到应用市场上供用户下载使用,比如上传到应用宝啊,应用汇啊,360啊,小米,华为,魅族啊,等等但是,有时候我们会经常遇到一些很扯淡的事情,刚 ...