Coding4Fun: 使用CSS网格布局&混合 5构建下降 block 游戏

分享于 

28分钟阅读

Web开发

  繁體 雙語

我想与你分享一个神秘的内部秘密保存在微软的一段时间内。 behind 网格布局的概念,微软设想的IE10和 Windows 商店应用。 大多数人可能认为这个规范是为了帮助开发人员为他们的网站和应用程序提供更好的布局引擎。 但是最初的动机完全不同。 第一个目的是能够以简单的方式创建一个下降的block 游戏 ! 但是我相信你还不确定。 这就是为什么我要用混合 5作为伴侣来证明。 行了,开始吧 !

pre必需:要遵循本教程,你需要首先:

步骤 1: 由于混合 5,发现了 behind 网格布局的秘密

启动表达式 Blend 5并创建一个新的空白应用程序的HTML ( Windows 存储) 项目。 将它的命名为" TheRealCSSGridStory":

image

替换:

<p>Content goes here</p>

使用:

<divclass="mainGrid"></div>

让我们创建一个包含 10列和 20行的网格,无论屏幕分辨率如何使用分数单位。 为此,添加这里CSS规则:

.mainGrid {
 display<span class="code-none"><span class="code-none">: -ms-grid<span class="code-none"><span class="code-none">;
 width<span class="code-none"><span class="code-none">: 100%<span class="code-none"><span class="code-none">;
 height<span class="code-none"><span class="code-none">: 100%<span class="code-none"><span class="code-none">;
 -ms-grid-columns<span class="code-none"><span class="code-none">: (1fr)[10]<span class="code-none"><span class="code-none">;
 -ms-grid-rows<span class="code-none"><span class="code-none">: (1fr)[20]<span class="code-none"><span class="code-none">;<span class="code-none"><span class="code-none">}</span></</span></span></span></span></span></span></span></span></span></span>span></</span>

在 Live DOM中选择 <div> mainGrid 元素,你应该得到以下结果:

image

让我们画一个形状 inside 这个美丽的网格。 将这里 block inside的添加到主网格中:

<divclass="shape1"></div>

插入与之关联的CSS:

.shape1 {
 -ms-grid-column<span class="code-none"><span class="code-none">: 4<span class="code-none"><span class="code-none">;
 -ms-grid-row<span class="code-none"><span class="code-none">: 3<span class="code-none"><span class="code-none">;
 -ms-grid-column-span<span class="code-none"><span class="code-none">: 3<span class="code-none"><span class="code-none">;
 -ms-grid-row-span<span class="code-none"><span class="code-none">: 2<span class="code-none"><span class="code-none">;
 background-color<span class="code-none"><span class="code-none">: red<span class="code-none"><span class="code-none">;<span class="code-none"><span class="code-none">}</span></</span></span></span></span></span></span></span></span></span></span>span></</span>

你现在应该在 Blend 5中看到了:

image

酷,但现在似乎还没有达到 block 游戏片的效果。 让我们来处理这个问题。将这些 2 DIV inside 添加到 shape1:

<divclass="line1shape1"></div><divclass="line2shape1"></div>

然后用这个CSS的block 替换以前的.shape1 规则:

.shape1 {
 -ms-grid-column<span class="code-none"><span class="code-none">: 4<span class="code-none"><span class="code-none">;
 -ms-grid-row<span class="code-none"><span class="code-none">: 3<span class="code-none"><span class="code-none">;
 -ms-grid-column-span<span class="code-none"><span class="code-none">: 3<span class="code-none"><span class="code-none">;
 -ms-grid-row-span<span class="code-none"><span class="code-none">: 2<span class="code-none"><span class="code-none">;
 display<span class="code-none"><span class="code-none">: -ms-grid<span class="code-none"><span class="code-none">;
 -ms-grid-columns<span class="code-none"><span class="code-none">: 1fr1fr 1fr<span class="code-none"><span class="code-none">;
 -ms-grid-rows<span class="code-none"><span class="code-none">: 1fr 1fr<span class="code-none"><span class="code-none">;
 width<span class="code-none"><span class="code-none">: 100%<span class="code-none"><span class="code-none">;
 height<span class="code-none"><span class="code-none">: 100%<span class="code-none"><span class="code-none">;<span class="code-none"><span class="code-none">}
.line1shape1<span class="code-none"><span class="code-none">{
 -ms-grid-column-span<span class="code-none"><span class="code-none">: 2<span class="code-none"><span class="code-none">;
 background-color<span class="code-none"><span class="code-none">: red<span class="code-none"><span class="code-none">;<span class="code-none"><span class="code-none">}
.line2shape1<span class="code-none"><span class="code-none">{
 -ms-grid-column<span class="code-none"><span class="code-none">: 2<span class="code-none"><span class="code-none">;
 -ms-grid-row<span class="code-none"><span class="code-none">: 2<span class="code-none"><span class="code-none">;
 -ms-grid-column-span<span class="code-none"><span class="code-none">: 2<span class="code-none"><span class="code-none">;
 background-color<span class="code-none"><span class="code-none">: red<span class="code-none"><span class="code-none">;<span class="code-none"><span class="code-none">}</span></</span></span></span></span></span></span></span></span>span></</span>span></</span></span></span></span></span>span></</span>span></</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>span></</span>

shape1当前在 3列和 2行上进行扩展。 我将创建一个新的网格 inside,这个区域由 3列和 2行定义,以使单元格与主网格的大小相同。

完成后,我将创建 2条线,以模拟下降 block 游戏的Z 形。 你现在应该具有以下结果:

z-shape in Tetris

最好是使用设备选项卡中的各种视图,你将会看到我们的游戏已经实现了一个响应性的设计工具。 ! 这真是太酷了,不是? https://www.codeproject.com/script/Forums/Images/smiley_smile.gif"/>

下面是捕捉视图和 portrait 视图的输出:


z-shape in landscape view

让我们来解决另一个问题。 下降的block 网格游戏网格由方块组成。 我们目前的React设计是拉伸 100%宽度。 为 Windows 商店构建 Windows 8应用程序将大部分时间都满足宽屏显示器( 当前平板电脑为 1366或者 1920 x1080,大多数台式电脑均具有 16/9 比)。 让我们假设以宽宽比为目标处理几乎所有案例。 要计算适当的响应宽度,需要执行以下操作: 9/16 * 10/20 ( 主游戏网格的比例),等于: 28.125%。

添加这里规则以在全屏 landscape 模式下对主网格进行定位:

@mediascreenand(-ms-view-state: fullscreen-landscape) {
 .mainGrid {
 width<span class="code-none"><span class="code-none">: 28.125%<span class="code-none"><span class="code-none">;
 <span class="code-none"><span class="code-none">}}</span></</span></span>span></</span>

现在让我们用。center。 CSS网格布局 ! ( 你现在应该开始相信它真的是为 block 游戏而设计的)。

用 1列 & 1行创建的 body 元素:

body {
 display<span class="code-none"><span class="code-none">: -ms-grid<span class="code-none"><span class="code-none">;
 -ms-grid-columns<span class="code-none"><span class="code-none">: 1fr<span class="code-none"><span class="code-none">;
 -ms-grid-rows<span class="code-none"><span class="code-none">: 1fr<span class="code-none"><span class="code-none">;
 width<span class="code-none"><span class="code-none">: 100%<span class="code-none"><span class="code-none">;
 height<span class="code-none"><span class="code-none">: 100%<span class="code-none"><span class="code-none">;<span class="code-none"><span class="code-none">}</span></</span></span></span></span></span></span></span></span></span></span>span></</span>

现在将这里属性添加到与主网格关联的CSS中:

-ms-grid-column-align: center;

网格现在是居中的:

在这个阶段你可能已经。 我怎么会错过这个不可思议的秘密? 你想知道。 现在,让我们继续这个教程,以发现由CSS规范组合在一起的它的他令人吃惊的可以能性。

步骤 2: 移动或者旋转形状

我的第一个想法是尽量使用尽可能多的CSS来避免 JS。 然后我首先尝试使用动画在不同行/列上移动图形的动画。 但是坏消息是,你不能通过CSS3动画改变 -ms-grid-column 或者 -ms-grid-row 值。 这将是一些JavaScript代码的工作。

然后我开始思考如何旋转形状。 CSS转换插件似乎完全适合。 我们来做一些实验。 混合 5真的很酷,因为你可以直接看到你的改变的结果。

通过将这里类添加到它的DIV元素,在 shape1 上添加 90度旋转:

.shape1rotated {
 transform<span class="code-none"><span class="code-none">: rotate(90deg)<span class="code-none"><span class="code-none">;<span class="code-none"><span class="code-none">}</span></</span></span>span></</span>

我确定你不希望这样:

Rotated shape

问题:它与游戏网格没有正确对齐。 要将我们的形状与网格对齐,需要进行一些小调整:

.shape1rotated {
 transform-origin<span class="code-none"><span class="code-none">: 33% 50%<span class="code-none"><span class="code-none">;
 transform<span class="code-none"><span class="code-none">: rotate(90deg) translateX(-33%)<span class="code-none"><span class="code-none">;<span class="code-none"><span class="code-none">}</span></</span></span></span></span>span></</span>

我们现在的旋转与 block 游戏的旋转相同。 在旋转之前/之后,这里有 2个屏幕截图:

旋转前的z 形状

旋转后的z 形

我们甚至可以通过使用shape1上的转换来进一步执行以下操作:

transition:all1s ease-out;

现在,在 shape1 DIV上删除/添加 .shape1rotated 类将会触发一个平滑的旋转动画 !

在这个阶段,我们可以认为这个方法是构建我们的游戏的好方法。 但不幸的是,这并不是。 这就是为什么尝试移动形状,只需更改它的-ms-grid-column 属性。 Blend 5将直接反映更改。 如果不旋转,则可以将形状向上移动到 8th 列:

z 形移动到 8th 列

到目前为止非常好但是,当你将 .shape1rotated 类添加到DIV中时,将它的旋转:

z 形旋转到 8th 列

你可以看到,右边还有 1行可以用于形状的移动。 如果你认为我们只需要把它移到 9th 行,你就错了 ! 实际上,我们将在 9th 行获得以下内容:

当移动到 9th 行时,z 形被压缩

你可能忘记了我们目前移动一个显示 3列和 2行的DIV元素,该布局与底层游戏网格完全匹配。 移动时我们感觉这是我们移动的主栅格的一块。 但是为了使这些技巧有效,我们至少需要 3列来包含我们的形状元素。 如果包含 2列( 当设置为 9th 列时) 或者 LESS,它将像屏幕截图中的"压缩"一样。

有 2种方法可以解决。

  • 停止使用CSS转换,使用其他网格定义绘制旋转的形状。 例如使用 3 inside 形状而不是 2. 但是使用这种方法将会阻止我们使用漂亮的CSS动画。
  • 重新定义主网格以处理 12列而不是 10,我们将仅使用 2中的列到( 如果你愿意的话,那就是一种剪辑区域)。 这将解决我们的"overflow"问题。

让我们来实现 2nd 解决方案。

使用以下方法重新定义主网格:

.mainGrid {
 display<span class="code-none"><span class="code-none">: -ms-grid<span class="code-none"><span class="code-none">;
 -ms-grid-columns<span class="code-none"><span class="code-none">: (1fr)[12]<span class="code-none"><span class="code-none">;
 -ms-grid-rows<span class="code-none"><span class="code-none">: (1fr)[20]<span class="code-none"><span class="code-none">;
 -ms-grid-column-align<span class="code-none"><span class="code-none">: center<span class="code-none"><span class="code-none">; 
 width<span class="code-none"><span class="code-none">: 100%<span class="code-none"><span class="code-none">;
 height<span class="code-none"><span class="code-none">: 100%<span class="code-none"><span class="code-none">;<span class="code-none"><span class="code-none">}</span></</span></span></span></span></span></span></span></span></span></span></span></span>span></</span>

要获得适当的比率,你还需要更新关联的媒体查询:

@mediascreenand(-ms-view-state: fullscreen-landscape) {
 .mainGrid {
 width<span class="code-none"><span class="code-none">: 33.75%<span class="code-none"><span class="code-none">;
 <span class="code-none"><span class="code-none">}}</span></</span></span>span></</span>

33。75% = 9/16 *12/20

让我们添加"虚拟网格"来标注我们将能够移动形状的空间。 inside 主网格 DIV,插入:

<divclass="virtualGrid"></div>

这里CSS的block 关联:

.virtualGrid {
 -ms-grid-column<span class="code-none"><span class="code-none">: 2<span class="code-none"><span class="code-none">;
 -ms-grid-column-span<span class="code-none"><span class="code-none">: 10<span class="code-none"><span class="code-none">;
 -ms-grid-row-span<span class="code-none"><span class="code-none">: 20<span class="code-none"><span class="code-none">;
 border-right-style<span class="code-none"><span class="code-none">: dashed<span class="code-none"><span class="code-none">;
 border-left-style<span class="code-none"><span class="code-none">: dashed<span class="code-none"><span class="code-none">;
 background-color<span class="code-none"><span class="code-none">: #505A5A<span class="code-none"><span class="code-none">;<span class="code-none"><span class="code-none">}</span></</span></span></span></span></span></span></span></span></span></span></span></span>span></</span>

它将有助于用灰色 background 和一些虚线边框标注游戏区域。

现在,如果移动列 9上的Z 形,行 2,结果如下:

列 9处的z 形

如果我使用CSS转换旋转它,我可以在第 10列正确地移动它:

旋转的z 形正确移动到列 9 Bonus - 处理 portrait 模式:

如果你想要支持 portrait 模式( 这对于下降的block 网格游戏来说更好),请添加这里CSS媒体查询定义:

@mediascreenand(-ms-view-state: fullscreen-portrait) {
 .mainGrid {
 width<span class="code-none"><span class="code-none">: 106.66%<span class="code-none"><span class="code-none">;
 <span class="code-none"><span class="code-none">}}</span></</span></span>span></</span>

由于需要计算为= 16/9 * 12/20 = 106,66 %.

。landscape 中的菱形网格

步骤 3: 添加一些代码来处理游戏逻辑的一部分

现在我们已经使用纯 CSS & HTML代码解决了游戏的图形部分,我们需要在游戏区域中移动/转动。 通过一个JS对象来实现CSS逻辑,这个对象将被定义为 thanks WinJS.Class。

在 Visual Studio 2012中打开" TheRealCSSGridStory"。

在JS目录中创建一个 TetrisShapeZ.js 文件,并复制/粘贴这里代码:

(function () {
 "use strict";
 var ShapeZ = WinJS.Class.define(
 ///Constructor - columnIndex is optional. If provided, will define in which column the shape will startfunction (columnIndex) {
 // We're creating the equivalent of this HTML block :// <div class="shape1">// <div class="line1shape1"></div>// <div class="line2shape1"></div>// </div>this._shape1 = document.createElement("div");
 var line1 = document.createElement("div");
 var line2 = document.createElement("div");
 this._shape1.className = "shape1";
 line1.className = "line1shape1";
 line2.className = "line2shape1";
 this._shape1.appendChild(line1);
 this._shape1.appendChild(line2);
 // Boolean to indicate if the shape is in its default orientation mode or not// True means not rotated, false means rotatedthis._defaultOrientation = true;
 // Setting the column position in the main gridif (columnIndex) {
 this._currentColPos = columnIndex;
 this._shape1.style.msGridColumn = this._currentColPos;
 }
 else {
 this._currentColPos = 1;
 }
 // We always start at line 1this._currentLinePos = 1;
 // Boolean to know if the shape can be move/rotate or not// If true, this means we've reached the last line possiblethis._fixed = false;
 },
 {
 ///Specify in which HTML element displayed in CSS Grid you'd like to work with///width is the number of columns of the grid & height is the number of lines insertIntoGrid: function (element, width, height) {
 element.appendChild(this._shape1);
 this._gridWidth = width;
 this._gridHeight = height;
 // These are the left & bottom max limit for this shape// when displayed in default orientation modethis._maxLeft = width - 3;
 this._maxBottom = height - 1;
 },
 ///Rotate the Z shape 90 degrees anti/clockwise using CSS Transforms///by simply removing/adding the shape1rotated class rotate: function () {
 if (!this._fixed && this._defaultOrientation) {
 // rotating 90 degrees clockwise, it will trigger also the CSS Transition WinJS.Utilities.addClass(this._shape1, "shape1rotated");
 this._defaultOrientation = false;
 // the left limit is now +1 vs the default orientationthis._maxLeft = this._gridWidth - 2;
 }
 else {
 if (!this._fixed && this._currentColPos <this._maxLeft) {
 // removing the shape1rotated will automatically reset the shape// to its initial matrix and again the CSS Transition will do the animation for you WinJS.Utilities.removeClass(this._shape1, "shape1rotated");
 this._defaultOrientation = true;
 this._maxLeft = this._gridWidth - 3;
 }
 }
 },
 // Internal function called by public moveLeft/moveRight _moveHorizontally: function (direction) {
 if (!this._fixed && (this._currentColPos <this._maxLeft || direction === -1) && (this._currentColPos> 2 || direction === 1)) {
 this._currentColPos = this._currentColPos + direction;
 this._shape1.style.msGridColumn = this._currentColPos;
 }
 },
 ///Move the shape on the immediate left column///Test if you've reached the left limit or not moveLeft: function () {
 this._moveHorizontally(-1);
 },
 ///Move the shape on the immediate right column///Test if you've reached the right limit or not moveRight: function () {
 this._moveHorizontally(1);
 },
 ///Move the shape down on the immediate below line///Test if you've reached the bottom limit or not moveDown: function () {
 if (!this._fixed) {
 this._currentLinePos = this._currentLinePos + 1;
 this._shape1.style.msGridRow = this._currentLinePos;
 if (this._currentLinePos === this._maxBottom) {
 this._fixed = true;
 }
 }
 }
 }
 );
 WinJS.Namespace.define("CSSTetris", { ShapeZ: ShapeZ });
} ());

只需阅读代码以了解它在做什么。 应该对它进行足够的注释,以便。

在 default.html 中添加对此脚本文件的引用,并只保留正文的这里 block:

<divclass="mainGrid"><divclass="virtualGrid"></div></div>

跳到 default.js。

拥有良好文档代码的最酷部分是我们现在有了有趣的智能感知细节,如对构造函数:

。ShapeZ(columnIndex) 构造函数的智能感知

或者 rotate 函数:

旋转函数的智能感知

要正确使用这里代码,请在 processAll 调用之后添加这里 block的:

document.addEventListener("keydown", OnKeyDown, false);
mainGrid = document.getElementsByClassName("mainGrid")[0];
myShape = new CSSTetris.ShapeZ(4);
myShape.insertIntoGrid(mainGrid, 12, 20);
init();

添加以下 2个函数:

function init() {
 setInterval(function () {
 myShape.moveDown();
 }, 1000);
}function OnKeyDown(event) {
 switch (event.keyCode) {
 case KEYCODE_X:
 myShape.rotate();
 break;
 case KEYCODE_LEFT:
 myShape.moveLeft();
 break;
 case KEYCODE_RIGHT:
 myShape.moveRight();
 break;
 case KEYCODE_DOWN:
 myShape.moveDown();
 break;
 }
}

这一切都已经完成了我们现在使用CSS网格布局和CSS转换图形部分和一对JS代码,以获得一个下降游戏基础的基础。

你可以下载与本教程的3步骤对应的final Visual Studio 解决方案: http://david.blob.core.windows.net/win8/TheRealCSSGridStory.zip

那么,你现在确信CSS网格布局是为了简化下降 block 游戏的创建? https://www.codeproject.com/script/Forums/Images/smiley_smile.gif"/>

本文是来自 IE 团队的HTML5技术系列的一部分。 在本文中试用 3个月的免费 BrowserStack 跨浏览器 测试 @ http://modern.IE

David是微软的一位开发者,专攻HTML5和web开发。 本文最初出现在他的MSDN博客上,Coding4Fun在 12上,. You 可以跟随他的@davrous 在 Twitter 上。


构建  GAM  GRID  Building  Layout  Block  
相关文章