blend 5_使用CSS网格布局和Blend 5构建游戏

blend 5

我想与您分享一个长期存在于Microsoft内部的神秘内部秘密。 这是Microsoft为IE10和Windows Store Apps想象的CSS网格布局概念的真实故事。

你们中的大多数人可能认为该规范旨在为开发人员提供用于其网站和应用程序的更好的布局引擎。 但是最初的动机是完全不同的。 最初的目标是能够以简单的方式创建类似Tetris的游戏!

我确定您还没有说服。 这就是为什么我将使用Blend 5作为伴侣向您证明这一点的原因。 好了,走吧!

先决条件:要学习本教程,您首先需要:

  1. 在您的计算机上下载/购买并安装Windows 8 RTMhttp : //msdn.microsoft.com/zh-CN/windows/apps/br229516.aspx
  2. 下载并安装Windows 8的Visual Studio 2012 Express RTM的免费版本: http : //msdn.microsoft.com/zh-cn/windows/apps/br229516.aspx ,其中包括适用于Visual Studio的Expression Blend 5或使用更高版本。

第1步:借助Blend 5,发现CSS网格布局背后的秘密

启动Expression Blend 5并创建一个空白应用程序类型的新HTML(Windows应用商店)项目。 将其命名为“ TheRealCSSGridStory ”:

图片

更换:

 < p > Content goes here </ p >
 

带有:

 < div  class ="mainGrid">
</ div >
 

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

 .mainGrid  {
    display : -ms-grid ;
    width : 100% ;
    height : 100% ;
    -ms-grid-columns : (1fr)[10] ;
    -ms-grid-rows : (1fr)[20] ;
}

在实时DOM中选择<div> mainGrid元素,您将获得以下信息:

图片

让我们在这个美丽的网格中绘制一个形状。 在主网格内添加以下HTML块:

 < div  class ="shape1">
</ div >
 

并插入与此关联CSS:

 .shape1  {
    -ms-grid-column : 4 ;
    -ms-grid-row : 3 ;
    -ms-grid-column-span : 3 ;
    -ms-grid-row-span : 2 ;
    background-color : red ;
}

您现在应该在Blend 5中看到这一点:

图片

很酷,但是对俄罗斯方块游戏来说,看起来还没有什么。 让我们继续努力。 在shape1中添加以下两个DIV:

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

并使用以下CSS块替换之前的.shape1规则:

 .shape1  {
    -ms-grid-column : 4 ;
    -ms-grid-row : 3 ;
    -ms-grid-column-span : 3 ;
    -ms-grid-row-span : 2 ;
    display : -ms-grid ;
    -ms-grid-columns : 1fr 1fr 1fr ;
    -ms-grid-rows : 1fr 1fr ;
    width : 100% ;
    height : 100% ;
}
.line1shape1  {
    -ms-grid-column-span : 2 ;
    background-color : red ;

}

.line2shape1  {
    -ms-grid-column : 2 ;
    -ms-grid-row : 2 ;
    -ms-grid-column-span : 2 ;
    background-color : red ;
}

shape1当前跨三列两行。 然后,我将在此区域内创建一个新的网格,该网格由三列和两行定义,以便使单元具有与主网格的单元完全相同的大小,而不管分辨率如何。

完成后,我将创建两条线以模仿俄罗斯方块游戏的Z形。 您现在应该得到以下结果:

免费学习PHP!

全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。

原价$ 11.95 您的完全免费

俄罗斯方块中的Z形

更好的是,使用“设备”选项卡中的各种视图进行操作,您会发现我们的游戏已经实现了自适应设计 ! 这真是太酷了,不是吗?

例如,以下是快照视图和纵向视图的输出:


横向视图中的Z形

现在让我们解决另一个问题。

俄罗斯方块网格游戏网格由正方形组成。 我们当前的响应式设计正在拉伸100%的宽度。 在大多数情况下,为Windows应用商店构建Windows 8应用程序将满足宽屏显示器的要求(当前的平板电脑为1366×768或1920×1080,大多数台式机的比例为16/9)。 然后,让我们假设针对宽屏比例可以解决几乎所有情况。 要计算适当的响应宽度,您需要执行:9/16 * 10/20(主游戏网格的比率),等于: 28.125%。

添加此规则以在全屏横向模式下定位主网格:

 @media  screen and (-ms-view-state: fullscreen-landscape) {
    .mainGrid  {
        width : 28.125% ;
        }
}

现在让我们再次使用CSS网格布局来居中游戏网格! (现在您应该开始相信它是真正为俄罗斯方块设计的!)

body元素切换到由一列和一行组成的–ms-grid

 body  {
    display : -ms-grid ;
    -ms-grid-columns : 1fr ;
    -ms-grid-rows : 1fr ;
    width : 100% ;
    height : 100% ;
}

现在,只需将此属性添加到与主网格关联CSS中即可:

 -ms-grid-column-align : center ;

网格现在居中:

在这个阶段,您可能已经感到震惊。 “ 我怎么会错过这个不可思议的秘密? ”您在想自己。

喘口气。

现在您已经知道了秘密,让我们一起继续本教程,以发现由CSS规范结合在一起提供的其他绝佳功能。

步骤2:移动或旋转形状

我的第一个想法是尝试通过使用尽可能多CSS来避免JS。 然后,我首先尝试使用CSS3动画在各个行/列上移动和设置形状的动画。 但坏消息是您无法通过CSS3动画更改–ms-grid-column–ms-grid-row值。 然后,这将是一些JavaScript代码的工作。

然后,我开始考虑如何旋转形状。 CSS Transforms似乎非常适合于此。 让我们通过做一些实验来检查一下。 Blend 5真的很酷,因为您可以直接实时看到更改的结果。

通过将class添加到其DIV元素,在shape1上添加90度旋转:

 .shape1rotated  {
    transform : rotate(90deg) ;
}

我确定您没有想到这一点:

Rotated shape

问题:它与游戏网格的排列不正确。 为了使形状与网格对齐,我们需要进行一些小的调整:

 .shape1rotated  {
    transform-origin : 33% 50% ;
    transform : rotate(90deg) translateX(-33%) ;
}

现在,我们具有与类似俄罗斯方块的游戏相同的旋转方式。 这是旋转前后的两个屏幕截图:

旋转前的Z形
旋转后的Z形

通过以下方式,我们甚至可以通过在shape1上使用过渡集来做进一步的工作:

 transition : all 1s ease-out ;

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

借助这段简短的视频,您可以在Blend 5中查看结果:

下载视频: VideoJS的MP4WebMHTML5视频播放器

在这个阶段,我们可以认为这种方法是构建我们游戏的好方法。 不幸的是,事实并非如此。 这就是为什么。 尝试通过简单更改其–ms-grid-column属性来移动形状。 Blend 5将直接反映更改。 不旋转时,形状可以向上移动到第八列:

Z形移至第8列

到目前为止,一切都很好。 但是,当您通过将.shape1rotated类添加到DIV来旋转它时:

Z形旋转到第8列

您会看到右侧还有1行可用于形状移动。 如果您认为我们只需要将其移至第9行,那就错了! 确实,这是我们将在第9行获得的结果:

Z形移到第9行时会被压缩

您可能忘记了我们当前正在移动一个DIV元素,该元素显示的网格布局完全与基础游戏网格匹配,三列两行。 在移动它时,我们确实感觉到这是我们要移动的主网格的一个块部分。 但是,要使此技巧起作用,我们至少需要三列可用于包含shape元素。 如果它包含在两列(或设置为第9列)中或更少,则将被“压缩”,如屏幕截图所示。

有两种解决方法。

1 –停止使用CSS变换,并使用另一个网格定义绘制旋转的形状。 例如,在形状内使用三个div而不是两个。 但是使用这种方法将阻止我们使用合适CSS动画。
2 –重新定义了主网格,使其可以处理12列而不是10列,并且我们将仅使用2到11列(如果需要,可以使用某种裁剪区域)。 这将解决我们的“溢出”问题。

让我们实现第二个解决方案。

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

 .mainGrid  {
    display : -ms-grid ;
    -ms-grid-columns : (1fr)[12] ;
    -ms-grid-rows : (1fr)[20] ;
    -ms-grid-column-align : center ;    
    width : 100% ;
    height : 100% ;
}

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

 @media  screen and (-ms-view-state: fullscreen-landscape) {
    .mainGrid  {
        width : 33.75% ;
        }
}

33.75%= 9/16 * 12/20

让我们还添加一个“虚拟网格”来界定我们将能够移动形状的空间。 在主网格DIV中,插入以下内容:

 < div  class ="virtualGrid">
</ div >
 

与此CSS块相关联:

 .virtualGrid  {
    -ms-grid-column : 2 ;
    -ms-grid-column-span : 10 ;
    -ms-grid-row-span : 20 ;
    border-right-style : dashed ;
    border-left-style : dashed ;
    background-color : #505A5A ;
}

这将有助于使用灰色背景和一些虚线边框来界定游戏区域。

现在,如果我在第9列第2行上移动Z形状,则结果如下:

第9栏的Z形

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

旋转的Z形正确移动到第9列

奖励–处理人像模式:

如果您想支持纵向模式(这对于俄罗斯方块游戏来说更好),请添加以下CSS Media Query定义:

 @media  screen and (-ms-view-state: fullscreen-portrait) {
        .mainGrid  {
        width : 106.66% ;
        }
}

由于该比率需要计算为= 16/9 * 12/20 = 106.66%。

俄罗斯方块网格在风景中

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

现在,我们仅使用一些纯CSS和HTML代码解决了游戏的图形部分,我们需要JavaScript的帮助才能在游戏区域中移动/旋转形状。 我们将通过WinJS.Class来定义一个JS对象,以重新实现CSS逻辑。

在Visual Studio 2012中打开“ TheRealCSSGridStory ”。

在JS目录中创建TetrisShapeZ.js文件,然后复制/粘贴以下代码:

( function  () {
    "use strict" ;

    var  ShapeZ = WinJS.Class.define(
    /// Constructor - columnIndex is optional. If provided, defines the column the shape starts in
         function  (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 rotated
             this ._defaultOrientation = true ;
            // Setting the column position in the main grid
             if  (columnIndex) {
                this ._currentColPos = columnIndex;
                this ._shape1.style.msGridColumn = this ._currentColPos;
            }
            else  {
                this ._currentColPos = 1;
            }
            // We always start at line 1
             this ._currentLinePos = 1;
            // Boolean to know if the shape can be move/rotate or not
            // If true, this means we've reached the last line possible
             this ._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 mode
                 this ._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 orientation
                     this ._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中添加对此脚本文件的引用,并在主体中仅保留以下HTML块:

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

跳到default.js

拥有完善文档的代码,最酷的部分是我们现在有了有趣的IntelliSense详细信息,例如构造函数

Intellisense for ShapeZ(columnIndex)构造函数

旋转功能:

Intellisense旋转功能

为了正确使用此代码,请在processAll调用之后添加此JS块:

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

并添加以下两个功能:

 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 Grid Layout结合图形部分CSS Transforms&Animations和几行JS代码来开始类似Tetris的游戏基础。

这是演示最终结果的简短视频:

下载视频: VideoJS的MP4WebMHTML5视频播放器

您可以在此处下载与本教程的三个步骤相对应的最终Visual Studio解决方案: http : //david.blob.core.windows.net/win8/TheRealCSSGridStory.zip

那么,您现在是否确信CSS网格布局是为了简化类似俄罗斯方块的游戏的创建而设计的?


本文是Internet Explorer团队HTML5技术系列的一部分。 通过3个月的免费BrowserStack跨浏览器测试@ http://modern.IE来尝试本文中的概念。


本文最初于2013年2月12日发表在David Rousset的MSDN博客Coding4Fun上。

翻译自: https://www.sitepoint.com/using-css-grid-layout-and-blend-5-to-build-a-game/

blend 5

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值