想要仅用HTML和CSS技术来打造《我的世界》的复制品吗?这听起来似乎有些不可思议,然而,确实有开发者实现了这一目标!现在,我们就来揭开这个故事的神秘面纱。
开发者的反套路操作
Aster这位开发者真是独具匠心,他竟然仅用HTML和CSS就成功制作出了《我的世界》的仿制品。按理说,制作这类游戏JavaScript几乎是必不可少的,但他却选择了另一条道路。该项目推出后,立刻引起了广泛关注,甚至英国的程序员Simon还专门撰写了一篇博客,对其中蕴含的技术秘密进行了深入解析。
克隆版游戏特点
这款游戏的表现相当不错。它构建了一个由九层、九行、九列构成的庞大虚拟世界,玩家可以在里面布置或撤销七种不同的元素。此外,玩家还能利用三维视角来旋转整个场景,实现全面观察。三维元素可以随意添加或移除,旋转视角浏览起来也非常顺畅,让人难以置信这一切竟然没有使用JavaScript技术。这场景仿佛看到一辆失去了动力核心却依然能疾驰而行的汽车,既让人感到难以置信,又充满了惊喜。
代码量惊人
让人惊讶的是,这个项目竟然只用到了480行CSS代码就完美收官。这么少的代码量,竟然能够支撑起一个运作良好的3D游戏世界,就好比用极少的材料搭建起一座高楼一样。一想到仅凭这么少的代码就能创造出如此惊人的效果,不禁让人由衷地赞叹这位开发者的技术确实非常高超。通常,制作一款游戏所需要编写的代码行数众多,常常是几百行,甚至上千行,而这个项目的代码却做到了极大的精简,确实让人十分惊叹。
关键技术原理
Simon 认为,项目能否顺畅进行,关键在于标签与 has() 选择器的巧妙搭配。每个方块的六个面都扮演着标签的角色,点击任何一个面,都能借助 for 属性精确地“连接”到邻近方块的状态。在 CSS 中,has() 选择器就如同一位机智过人的管家。当用户选择了“石头”这个选项,界面上的其他材质方块就会消失不见,只留下石头材质的方块清晰呈现。这样的设计很巧妙,能够根据玩家的选择,灵活地展示出不同类型的方块。
HTML 生成难题与解决办法
.controls:has(
> .block-chooser > .stone > input[type=radio]:checked
) ~ main .cubes-container > .cube:not(.stone) {
display: none;
}
此项目需要编写超过一万行的HTML代码,如果仅依赖人工来完成,那么整个过程将会变得极其漫长且效率低下。鉴于此,我们打算为729个立方体设计一套包含8个单选按钮的通用组合,这些按钮将拥有相同的名称属性。每个立方体都附有六个匹配的标签,这些标签与立方体的六个面一一对应。每个标签的for属性都指向了邻近的立方体,还有那些材质类型被选中的立方体。这种设计巧妙地解决了手写HTML时遇到的难题,同时也保障了项目的顺利进行。
项目初衷与意义
//- pug index.pug -w
- const blocks = ["air", "stone", "grass", "dirt", "log", "wood", "leaves", "glass"];
- const layers = 9;
- const rows = 9;
- const columns = 9;
<html lang="en" style="--layers: #{layers}; --rows: #{rows}; --columns: #{columns}">
<div class="blocks">
for _, layer in Array(layers)
for _, row in Array(rows)
for _, column in Array(columns)
<div class="cubes-container" style="--layer: #{layer}; --row: #{row}; --column: #{column}">
- const selectedBlock = layer === layers - 1 ? "grass" : "air";
- const name = `cube-layer-${layer}-row-${row}-column-${column}`;
<div class="cube #{blocks[0]}">
- const id = `${name}-${blocks[0]}`;
<input type="radio" name="#{name}" id="#{id}" !{selectedBlock === blocks[0] ? "checked" : ""} />
<label for="#{id}" class="front">label>
<label for="#{id}" class="back">label>
<label for="#{id}" class="left">label>
<label for="#{id}" class="right">label>
<label for="#{id}" class="top">label>
<label for="#{id}" class="bottom">label>
div>
each block, index in blocks.slice(1)
- const id = `${name}-${block}`;
- const checked = index === 0;
<div class="cube #{block}">
<input type="radio" name="#{name}" id="#{id}" !{selectedBlock === block ? "checked" : ""} />
<label for="cube-layer-#{layer}-row-#{row + 1}-column-#{column}-#{block}" class="front">label>
<label for="cube-layer-#{layer}-row-#{row - 1}-column-#{column}-#{block}" class="back">label>
<label for="cube-layer-#{layer}-row-#{row}-column-#{column + 1}-#{block}" class="left">label>
<label for="cube-layer-#{layer}-row-#{row}-column-#{column - 1}-#{block}" class="right">label>
<label for="cube-layer-#{layer - 1}-row-#{row}-column-#{column}-#{block}" class="top">label>
<label for="cube-layer-#{layer + 1}-row-#{row}-column-#{column}-#{block}" class="bottom">label>
div>
//- /each
div>
//- /for
//- /for
//- /for
div>
三年前,这个项目开始了,开发者那时做了一项实验,想看看纯 CSS 能做到什么程度。他用了当时浏览器新推出的 :has() 选择器。从这个角度来说,他确实实现了他的目标。他只用了480行CSS和超过4万行的HTML,就做出了一个3D空间,能放方块、盖房子、还能调整视角。这充分证明了他卓越的技艺水平,并且向开发者们展示了新技术的广阔探索空间。
大家普遍认为,未来这样的低代码却功能强大的项目是否会逐渐增多?别忘了点赞,并将这篇文章转发出去,同时也可以在评论区分享你的观点。