返回

穿越2D与3D:基于HTML5与WebGL的3D第一人称碰撞漫游

前端

探索3D迷宫世界的奇妙之旅:基于HTML5和WebGL的沉浸式碰撞漫游游戏

沉浸在3D迷宫的奇幻世界

踏入这个令人惊叹的3D世界,化身一名无所畏惧的探险家,穿梭在巧妙设计的迷宫中。每一处转弯、每一场遭遇,都将在3D空间中激荡着真实的碰撞,让你的冒险之旅充满挑战与刺激。

WebGL与HTML5的强强联手

WebGL的3D图形渲染魔力与HTML5的灵活性相辅相成,为我们创造了一个逼真的虚拟天地。在这个3D第一人称视角的游戏中,你将仿佛置身于另一个真实的存在中,体验与虚拟世界的每一次互动。

以第一人称视角领略真实

我们的游戏采用了第一人称视角,让你宛如身临其境,而非隔岸观火。随着你的移动,周围的环境也将随之变化,营造出一种令人信服的移动感,让你真正感受到虚拟世界的魅力。

真实的碰撞,真实的挑战

为了让你的冒险更加真实,我们加入了逼真的碰撞检测。这意味着当你的虚拟形象与游戏中的物体相遇时,它们会产生物理碰撞,无法相互穿透。这种碰撞系统让游戏世界更加逼真,让你在探索过程中时刻感受到真实感。

精心设计的迷宫,挑战你的智慧

迷宫是游戏中不可或缺的元素,也是你智力与探索能力的考验。我们精心构思了错综复杂的迷宫,布满了各种障碍和岔路,引诱着你深入探索。只有细心观察,运用智慧,你才能找到正确的路径,到达迷宫的终点。

仅用300行代码,创造非凡体验

这款游戏的另一个惊人之处在于其代码量——仅约300行。这归功于HTML5和WebGL强大的功能,使开发者能够用更少的代码实现更多丰富的效果。

HTML代码示例:

<canvas id="myCanvas" width="500" height="500"></canvas>

<script>
// 获取画布元素
var canvas = document.getElementById("myCanvas");

// 创建WebGL渲染上下文
var gl = canvas.getContext("webgl");

// 设置视口
gl.viewport(0, 0, canvas.width, canvas.height);

// 创建着色器程序
var program = gl.createProgram();

// 编译着色器
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);

// 加载着色器代码
var vertexShaderSource = `
    attribute vec3 a_position;
    uniform mat4 u_projectionMatrix;
    uniform mat4 u_viewMatrix;
    uniform mat4 u_modelMatrix;
    void main() {
        gl_Position = u_projectionMatrix * u_viewMatrix * u_modelMatrix * a_position;
    }
`;

var fragmentShaderSource = `
    precision mediump float;
    uniform vec4 u_color;
    void main() {
        gl_FragColor = u_color;
    }
`;

gl.shaderSource(vertexShader, vertexShaderSource);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(vertexShader);
gl.compileShader(fragmentShader);

// 附加着色器到程序
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);

// 链接程序
gl.linkProgram(program);

// 使用程序
gl.useProgram(program);

// 创建缓冲区
var buffer = gl.createBuffer();

// 绑定缓冲区
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);

// 填充缓冲区数据
var vertices = new Float32Array([
    -0.5, -0.5, 0.0,
    0.5, -0.5, 0.0,
    0.0, 0.5, 0.0
]);

gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

// 获取属性位置
var positionLocation = gl.getAttribLocation(program, "a_position");

// 启用属性
gl.enableVertexAttribArray(positionLocation);

// 绑定属性到缓冲区
gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);

// 创建颜色数组
var colors = new Float32Array([
    1.0, 0.0, 0.0, 1.0,
    0.0, 1.0, 0.0, 1.0,
    0.0, 0.0, 1.0, 1.0
]);

// 创建颜色缓冲区
var colorBuffer = gl.createBuffer();

// 绑定颜色缓冲区
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);

// 填充颜色缓冲区数据
gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);

// 获取颜色属性位置
var colorLocation = gl.getAttribLocation(program, "a_color");

// 启用颜色属性
gl.enableVertexAttribArray(colorLocation);

// 绑定颜色属性到缓冲区
gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0);

// 创建投影矩阵
var projectionMatrix = mat4.create();
mat4.perspective(projectionMatrix, 45, canvas.width / canvas.height, 0.1, 100.0);

// 创建视图矩阵
var viewMatrix = mat4.create();
mat4.translate(viewMatrix, viewMatrix, [0.0, 0.0, -3.0]);

// 创建模型矩阵
var modelMatrix = mat4.create();

// 绘制循环
function render() {
    // 清除颜色缓冲区
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT);

    // 设置模型矩阵
    mat4.rotate(modelMatrix, modelMatrix, 0.01, [0.0, 1.0, 0.0]);

    // 设置投影矩阵
    gl.uniformMatrix4fv(gl.getUniformLocation(program, "u_projectionMatrix"), false, projectionMatrix);

    // 设置视图矩阵
    gl.uniformMatrix4fv(gl.getUniformLocation(program, "u_viewMatrix"), false, viewMatrix);

    // 设置模型矩阵
    gl.uniformMatrix4fv(gl.getUniformLocation(program, "u_modelMatrix"), false, modelMatrix);

    // 绘制三角形
    gl.drawArrays(gl.TRIANGLES, 0, 3);

    // 请求下一次动画帧
    requestAnimationFrame(render);
}

// 启动绘制循环
render();
</script>

WebGL代码示例:

// 获取 WebGL 上下文
var gl = canvas.getContext("webgl");

// 编译顶点着色器
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
var vertexShaderSource = `
  attribute vec3 a_position;
  uniform mat4 u_projectionMatrix;
  uniform mat4 u_viewMatrix;
  uniform mat4 u_modelMatrix;
  void main() {
    gl_Position = u_projectionMatrix * u_viewMatrix * u_modelMatrix * a_position;
  }
`;
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);

// 编译片段着色器
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
var fragmentShaderSource = `
  precision mediump float;
  uniform vec4 u_color;
  void main() {
    gl_FragColor = u_color;
  }
`;
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);

// 创建程序并链接着色器
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);

// 使用程序
gl.useProgram(program);

// 查找属性和 uniform 变量的位置
var a_position = gl.getAttribLocation(program, 'a_position');
var u_projectionMatrix = gl.getUniformLocation(program, 'u_projectionMatrix');
var u_viewMatrix = gl.getUniformLocation(program, 'u_viewMatrix');
var u_modelMatrix = gl.getUniformLocation(program, 'u_modelMatrix');
var u_color = gl.getUniformLocation(program, 'u_color');

// 准备数据
var positions = new Float32Array([
  -0.5, -0.5, 0.0,
  0.5, -0.5, 0.0,
  0.0,