웹 프론트엔드 H5 튜토리얼 루빅스 큐브 게임을 구현하기 위한 HTML5 코드

루빅스 큐브 게임을 구현하기 위한 HTML5 코드

Aug 06, 2018 am 10:39 AM

이 글은 루빅큐브 게임을 HTML5로 구현하기 위한 코드를 공유합니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.

<!DOCTYPE html>
<html>
<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>
로그인 후 복사

관련 권장사항:

html5 모바일 풀다운 새로고침 구현(원리 및 코드)

H5 개발: 별을 파괴하는 게임 구현 세부정보

위 내용은 루빅스 큐브 게임을 구현하기 위한 HTML5 코드의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

H5 프로젝트를 실행하는 방법 H5 프로젝트를 실행하는 방법 Apr 06, 2025 pm 12:21 PM

H5 프로젝트를 실행하려면 다음 단계가 필요합니다. Web Server, Node.js, 개발 도구 등과 같은 필요한 도구 설치. 개발 환경 구축, 프로젝트 폴더 작성, 프로젝트 초기화 및 코드 작성. 개발 서버를 시작하고 명령 줄을 사용하여 명령을 실행하십시오. 브라우저에서 프로젝트를 미리보고 개발 서버 URL을 입력하십시오. 프로젝트 게시, 코드 최적화, 프로젝트 배포 및 웹 서버 구성을 설정하십시오.

H5 페이지 제작은 정확히 무엇을 의미합니까? H5 페이지 제작은 정확히 무엇을 의미합니까? Apr 06, 2025 am 07:18 AM

H5 Page 프로덕션은 HTML5, CSS3 및 JavaScript와 같은 기술을 사용하여 크로스 플랫폼 호환 웹 페이지의 생성을 말합니다. 핵심은 브라우저의 구문 분석 코드, 렌더링 구조, 스타일 및 대화식 기능에 있습니다. 일반적인 기술에는 애니메이션 효과, 반응 형 디자인 및 데이터 상호 작용이 포함됩니다. 오류를 피하려면 개발자를 디버깅해야합니다. 성능 최적화 및 모범 사례에는 이미지 형식 최적화, 요청 감소 및 코드 사양 등이 포함됩니다. 로딩 속도 및 코드 품질을 향상시킵니다.

뷰포트 메타 태그를 사용하여 모바일 장치에서 페이지 스케일링을 제어하려면 어떻게합니까? 뷰포트 메타 태그를 사용하여 모바일 장치에서 페이지 스케일링을 제어하려면 어떻게합니까? Mar 13, 2025 pm 08:00 PM

이 기사에서는 Viewport Meta 태그를 사용하여 모바일 장치의 페이지 스케일링을 제어하여 폭과 최적의 응답 성 및 성능을위한 초기 스케일과 같은 설정에 중점을 둡니다. character count : 159

HTML5 페이지 가시성 API를 사용하여 페이지가 표시되는시기를 감지하려면 어떻게합니까? HTML5 페이지 가시성 API를 사용하여 페이지가 표시되는시기를 감지하려면 어떻게합니까? Mar 13, 2025 pm 07:51 PM

이 기사에서는 HTML5 페이지 가시성 API를 사용하여 페이지 가시성을 감지하고 사용자 경험을 향상 시키며 리소스 사용량을 최적화하는 것에 대해 설명합니다. 주요 측면에는 미디어 일시 정지, CPU 부하 감소 및 가시성 변경에 기반한 분석 관리가 포함됩니다.

Geolocation API로 사용자 위치 개인 정보 및 권한을 어떻게 처리합니까? Geolocation API로 사용자 위치 개인 정보 및 권한을 어떻게 처리합니까? Mar 18, 2025 pm 02:16 PM

이 기사는 지리적 위치 API를 사용하여 사용자 위치 개인 정보 및 권한 관리, 권한 요청, 데이터 보안 보장 및 개인 정보 보호법 준수에 대한 모범 사례를 강조하는 것에 대해 설명합니다.

대화식 사용자 인터페이스에 HTML5 드래그 앤 드롭 API를 어떻게 사용합니까? 대화식 사용자 인터페이스에 HTML5 드래그 앤 드롭 API를 어떻게 사용합니까? Mar 18, 2025 pm 02:17 PM

이 기사는 HTML5 드래그 앤 드롭 API를 사용하여 대화식 사용자 인터페이스를 생성하고 요소를 드래그 가능하게 만들고 주요 이벤트를 처리하며 사용자 정의 피드백으로 사용자 경험을 향상시키는 방법을 자세히 설명합니다. 또한 일반적인 함정에 대해 설명합니다

H5를 만드는 방법 아이콘을 클릭하십시오 H5를 만드는 방법 아이콘을 클릭하십시오 Apr 06, 2025 pm 12:15 PM

H5 클릭 아이콘을 생성하는 단계에는 다음이 포함됩니다. 이미지 편집 소프트웨어에서 정사각형 소스 이미지 준비. H5 편집기에 상호 작용을 추가하고 클릭 이벤트를 설정하십시오. 전체 아이콘을 덮는 핫스팟을 만듭니다. 페이지로 점프하거나 애니메이션 트리거링과 같은 클릭 이벤트의 동작을 설정하십시오. h5 문서를 HTML, CSS 및 JavaScript 파일로 내보내십시오. 내보내는 파일을 웹 사이트 또는 기타 플랫폼에 배포하십시오.

H5 페이지 생산에는 지속적인 유지 보수가 필요합니까? H5 페이지 생산에는 지속적인 유지 보수가 필요합니까? Apr 05, 2025 pm 11:27 PM

코드 취약점, 브라우저 호환성, 성능 최적화, 보안 업데이트 및 사용자 경험 개선과 같은 요소로 인해 H5 페이지를 지속적으로 유지해야합니다. 효과적인 유지 관리 방법에는 완전한 테스트 시스템 설정, 버전 제어 도구 사용, 페이지 성능을 정기적으로 모니터링하고 사용자 피드백 수집 및 유지 관리 계획을 수립하는 것이 포함됩니다.

See all articles