禁止按tab时焦点从flash切换到地址栏
找了好久,终于在一个国外站点看到了解决方法:
1 2 3 4 5 6 7 8 9 | <script type="text/javascript">
document.onkeydown=function(){
if(event.keyCode==9){
event.keyCode=0;
event.returnValue=false;
return false;
}
};
</script> |
找了好久,终于在一个国外站点看到了解决方法:
1 2 3 4 5 6 7 8 9 | <script type="text/javascript">
document.onkeydown=function(){
if(event.keyCode==9){
event.keyCode=0;
event.returnValue=false;
return false;
}
};
</script> |
最近在学习用asdoc生成文档,我们在使用官方API文档的时候,都能看到有些类的底部会有关于这个类是如何使用的例子,他是如何做到的呢,其实用的就是这个指令:@includeExample xxx/example.as,在它后面跟的是例子的路径,但是有一点,我们不能因为想要写个小例子,就把它放在跟类相同的路径下吧,这会非常糟糕的,我们更希望把例子集中在一个文件夹下统一管理,有什么好办法吗,答案是肯定的。我们需要在编译语句后面加上-examples-path [盘符]:\[路径],它指的就是我们存放例子的路径,但是一定要记住,存放example的路径最好跟类文件的路径是一样的,这样管理起来更方便。比如我把框架放在d盘名为powerboy的目录下,框架里有个cn.pboy.control.Button的类,它的路径看起来像这样:d:\powerboy\cn\pboy\control\Button.as,现在我要对这个类添加例子,我想把例子统一放在d盘的examples文件夹下统一管理,那么路径应该是这样的:d:\examples\cn\pboy\control\ButtonExample.as,然后在命令行工具下把当前盘符设为d:\powerboy>,通过以下命名就可以编译了:asdoc -source-path . -doc-sources . -examples-path d:\examples
这里给出一个小例子,方便大家看到是否设置睡眠的区别。右上角的5个按钮代表重力方向,他们都是用向量模拟的,中间的按钮“无”代表失重状态。关于睡眠设置,默认是禁止睡眠,点击右侧按钮可以切换状态。通过观察你可以发现,当所有小球停止运动的时候,如果是禁止睡眠,当你改变重力方向的时候它们仍然可以运动,如果是允许睡眠的话,你会发现他们确实睡的跟死猪一样,一动不动。
需要看源码的朋友,请在下方留言,留下你的邮箱地址,我会尽快回复你的。
声明:以下文章是本人在学习过程中总结的一些个人经验,如果需要复制,请务必注明出处:http://www.p-boy.cn
现在网上关于as3的物理引擎真是不少,比较之后发现,在开源引擎当中Box2D算是比较不错的了,只可惜他的结构比较复杂,而且国内网站关于Box2D方面的教程真是少的可怜。因为我知道这个最早是c++上面的2D引擎,所以我找到了http://www.box2d.org/manual.html网址,经过几天的研究,总算是入门了,下面我会系统的针对官网给出的HelloWorld程序进行讲解,把个人心得分享给大家(鼓掌)!
这个引擎是先从创建一个世界对象开始的,他负责管理内部一切对象的内存和模拟过程。要创建一个世界中的对象,首先我们需要为世界定义边界区域,Box2D针对区域内的所有对象进行模拟碰撞,区域的大小并不重要,但更适合的区域将提高程序性能,一般来讲这个区域设置的要比演示区域更大一些,因为一旦对象在运动时到达了边界,它就会被“冻结”并停止一切模拟活动。
var worldAABB:b2AABB = new b2AABB(); worldAABB.lowerBound.Set(-100,-100);//左边界、上边界 worldAABB.upperBound.Set(100,100);//右边界、下边界
下面我们要为这个世界设置重力了,就是下面这段代码,其实这里面的重力是用向量b2Vec2(x,y);来表示的,x代表水平运动,正数向右,负数向左,y代表垂直运动,正数向下,负数向上。同时我们需要再定义一个布尔型参数(我命名为doSleep),来表示是否允许睡眠,睡眠所代表的含义网上也没有一个明确的介绍,这里我简要讲解一下。因为你在这个世界中生成的一切对象,他们的模拟效果都是实时计算出来的,当doSleep=false的时候,即使物体停止了运动,计算机还是在不停的进行着运算,其实这是完全不必要的,所以一般都设为true,这样当物体停止之后就不会进行无谓的cpu消耗了。
var gravity:b2Vec2 = new b2Vec2(0,10); var doSleep:Boolean = true;
以上参数都准备好了,我们可以将它们传入b2World对象中并将其实例化,这样一个物理引擎的模拟区域就做好了。
var world:b2World = new b2World(worldAABB,gravity,doSleep);
让我们开始在其中加入你想要模拟的对象吧。本来在那个英文网站中给出的是5个步骤,但是我感觉还少点什么,所以我又加了一条:
第一步、创建并定义刚体位置。这里我做一下名词解释,在任何力的作用下,体积和形状都不发生改变的物体叫做“刚体”;
var ground:b2BodyDef = new b2BodyDef(); ground.position.Set(10, 12);//这里的位置也是用向量定义的
2、给刚体定义皮肤(注意这里的皮肤并不具备物理引擎的属性,因此才有了第四步);
bodyDef.userData = _mc;//我们自己绘制的图形 addChild(bodyDef.userData);
3、用世界对象添加刚体实例,需要注意的是世界对象里并没有保存body定义的引用;
var body:b2Body = world.CreateBody(bodyDef);
4、根据皮肤形状创建模拟图形类:摩擦力、密度、弹力等等;当密度为0的时候,物体是不会动的,相当于障碍物。摩擦力和弹力取值范围是0~1,形状的区域是由SetAsBox定义的,因为模拟图形和刚体都要求以中心点为注册点,因此这里的宽和高的值都是一半,同时需要注意,这里数值单位并不是像素,而是米,1米=30像素,大家在传值的时候可别忘记换算哦。
var box:b2PolygonDef = new b2PolygonDef();//创建多边形 box.density = _density; box.friction = _friction; box.restitution = _restitution; box.SetAsBox(_halfWidth , _halfHeight);
5、在刚体上添加模拟图形实例;
body.CreateShape(box);
6、根据刚体的密度和面积计算出质量,密度*面积=质量。
body.SetMassFromShapes();
这里有两个重要的参数需要我们自己定义一下。一个是迭代次数,这里我定义为m_iterations,建议迭代次数为10,这时一个比较合理的值,使用较少的迭代可以提高性能,但模拟质量受到影响。同样,使用更多的迭代性能有所下降,但提高了你的模拟质量。另外一个参数是游戏的刷新频率,我定义为m_timeStep,根据英文教程上记载,它采用的是1/60秒刷新一次,但因为它的平台是c++,性能比AVM2虚拟机高出数倍,完全可以这么做,而在flash中我们一般设置成1/30就可以了。
var m_iterations:Number = 10; var m_timeStep:Number = 1 / 30;
现在一切都准备好了,我们要让所有对象模拟运动。其实他也是通过侦听帧频率而不断刷新实现的,把上面那两个参数传入世界对象的Step方法中即可,同时我们需要遍历世界中的一切对象,并对每个对象的坐标和角度进行更新。
addEventListener(Event.ENTER_FRAME, Update, false, 0, true); function Update(e:Event):void { world.Step(m_timeStep, m_iterations); for (var bb:b2Body=world.m_bodyList; bb; bb=bb.m_next) { if (bb.m_userData is Sprite) { bb.m_userData.x=bb.GetPosition().x * 30;//这里获取的变量单位是米,乘以30转换成像素单位 bb.m_userData.y=bb.GetPosition().y * 30; bb.m_userData.rotation=bb.GetAngle() * (180 / Math.PI); } } }
好了,现在相信大家已经对Box2D有了一定了解,赶快尝试制作一些效果吧。
最近我用一个单例模式类LoginNetManager对socket进行了封装,里面有一个send方法,专门用户向服务器发送事件,写法如下:
1 2 | LoginNetManager.getInstance().addEventListener(NetEvent.SOCKET_ERROR,onConnectError); LoginNetManager.getInstance().send(NetEvent.LS_MSG_ADDCONNECT); |
这个就是向服务器发送其中一个事件信息的语句,但奇怪的问题出现了,我在flashIDE本地进行测试的时候,一切正常,但是当我放到虚拟路径下测试的时候,它就会提示说“无法找到空对象引用的属性或方法”,我一看,问题就出在第二行那个send的方法,难道说类还没有完全实例化的时候,程序就继续向下运行了?但是这里也不存在异步执行啊,无奈之下,我修改成一个延迟语句:
1 2 | LoginNetManager.getInstance().addEventListener(NetEvent.SOCKET_ERROR,onConnectError); setTimeout(getSocket,500); |
我在getSocket方法中调用那条语句,问题就都解决了。这确实很蹊跷,我承认flash在本地运行与在网页中运行的时候,执行的是不同的flash player程序,但是从这个例子来讲,不同flash player之间的差异性还是显而易见的。
PureMVC是在基础的经典模型、视图和控制器上建立的一个轻量级的应用框架,这种开源框架是免费的,它最初是执行的ActionScript 3语言使用的Adobe Flex、Flash和AIR,现在已经移植到几乎所有主要的发展平台,目前支持两个版本框架:标准和多核,总之,标准版提供了一种简单的编码分离的方法,按照MVC设计概念。除此之外,多版本允许多个PureMVC应用运行在同一个虚拟机;模块化编程
框架概述
本文讨论PureMVC框架的类和接口,通过简单的UML(统一建模语言)图表阐述他们的作用、职责和合作。
PureMVC有一个非常狭隘的主要目标:用于帮助程序员分离代码为三个离散的层:即模型,视图和控制器。
在该经典的MVC元模式实现框架中,应用层有三个单例(一个只创建一次的类)所表示。而第四个单例,Façade类通过一个单一的接口为应用程序之间提供通讯,从而简化了开发。
模型(Model)简单的指向Proxy的引用。Proxy代码负责操作数据模型,与远程服务通信存取数据。
视图指向Mediator的引用。Mediator管理视图组件,增加事件监听器,操作视图组件的状态。
控制器包括命令类及其映射。命令类是无状态的,只有需要时才被创建。
Façade单例初始化Model, View, Controller,并且能访问各层类的Public方法。
Façade与核心类

Façade类令roxies, Mediators和Commands之间以松耦合的方式允许互相通信,而不需要导入或知道框架核心的存在。当我们创建一个Façade类具体的应用时,就可以“即开即用”的使用它了。附带的,与Façade类的交互将会最大化的降低开发者对API知识的了解程度。
核心成员类Model, View和Controller分别实现了IModel, IView 以及 IController 接口,Façade类实现了由核心接口组成的IFacade接口。
View, Mediators和View组件

View类被实现为一个用来缓存指向一个IMediator实例引用的单例。
Mediators类帮助我们创建或者重用已经存在的用户接口组件,而不用让他们通讯的PureMVC程序的知识去影响他们。具体的Mediators实例必须实现IMediator接口,通常是作为Mediator类的子类来实现的。
View视图用来显示数据和处理用户交互。在一个基于flash的应用程序中,他们通常通过使用事件和传递一些属性给其Mediators类去检查或者控制,以便与View的Mediators类交互。一个Mediator类通过View组件的数据与之建立联系。当一个Mediator 类的实例被view注册时,他会被假设为他需要获取通知。因此必须返回一个包含所有他感兴趣数据的通知名数组。
因为Mediator类必须实现IMediator接口,所以一个Mediator实例拥有handleNotification方法。当该实例被View组件注册,一个Observer实例就被创建并且被注册给每一个Notification的数组中。这样Mediator的handleNotification方法就被触发,而不论注册Notification的Mediator是否感兴趣。
Mediator类由于实现了INotifier接口而具备了sendNotification方法,sendNotification方法的参数是一个新的Notification通知,而后使用一个IFacade接口的单例去广播。

Mediator类的protected属性被初始化用于注册IFacade实例,并且因此Mediator必须在主程序初始化Façade实例后被注册。
Model, Proxies与数据对象

Model类被实现为一个简单的指向IProxy引用的单例。
Proxy类帮助我们暴露数据模型和实体类(当域逻辑和服务支持时)给应用程序,使得程序可以被其它地方被复用或重构。
我们可能通过使用一个Proxy实例来简化指向本地数据对象的管理,在这种情况下交互可能引起一些数据的同步操作。一个Proxy实例也可能被用来进行程序的原创服务操作,加载或者保持数据。这时,我们可能需要出发一个方法或者基于Proxy去设置数据,并且等待该Proxy从服务器成功加载到数据后广播一个Notification通知。
Proxy类由于实现了INotifier接口而具备了sendNotification方法,sendNotification方法的参数是一个新的Notification通知,而后使用一个IFacade接口的单例去广播。
Proxy类的protected属性被初始化用于注册IFacade实例,并且因此Mediator必须在主程序初始化Façade实例后被注册。
Controller与Commands

MacroCommand类从它的构造函数中触发initializeMacroCommand方法。使用者必须在其子类中重写initializeMacroCommand方法,一般addSubCommand方法添加所有Command。可以使用SimpleCommands 或者 MacroCommands中的任何一种。
View, Observer与Notification

Proxies,Mediators与Commands类之间的通讯是通过广播Notifications来实现松耦合和跨平台特性的:
Proxies可以发送,但不能接收Notification
Mediator声明感兴趣的Notification和接收Notification
Commands被触发或广播Notifications
PureMVC应用程序可能运行在不能访问Flash Event和EventDispatcher类的环境中,所以框架使用观察者模式以一种松耦合的方式在Model, View, Controller之间通信。
PureMVC使用观察者模式就是为了该目的。IObserver携带一个希望被关注(即“被关注的内容”)的对象引用,该对象的一个方法将会在INotification实例被广播(即“被关注方法”)时被触发。
View组件的职责是管理Notification的名称给Observer列表,以及当有Notification被发送时通知所有的Observers。
今天在公司,一同事问了我一个问题,我想写一个方法,当接收到任意长度整型数值的时候,我如何只保留首位,其他位全部置为0呢。我思考了几秒钟:你可以先把整型参数用String强类型转换,看看字符串的长度,这样你就能根据长度得到首位的数字,后面再根据长度补零就行了。这时他问道,可不可以不通过字符串转换,直接用整型来处理呢?于是我们开始研究:
第一种做法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | function encoder(num:int):int{ var sNum:int = num; var count:int = 0; while(true){ count++; sNum /= 10; if (sNum < 10){ sNum = Math.floor(sNum); break; } } return decoder(sNum,count); } function decoder(num:int,step:int):int{ var _num:int = num; for (var i:int = 0;i<step;i++){ _num *= 10; } return _num; } |
经过测试,这种做法是没有问题的,但是这是不是最好的方法呢,当然不是,因为Math.floor()的原因肯定会导致效率下降一部分,有办法替换么,其实很简单,直接用int()转换一下就行了。这样是最优做法么,当然还不是,看看下面这段代码:
第二种做法:
1 2 3 4 5 6 7 8 9 10 | function encoder(num:int):int{ var i:int=num; var j:int=1; while(i>10) { j*=10; i=num/j; } return i*j; } |
这段代码相信大家都能看懂,它的优化在哪呢?比之前少了一个循环,当然效率会大幅提升了。我们只需再添加一个变量作为被乘数,这样就减少了一个循环。这段代码基本已经是效率很高了,但其实如果你够细心的话,仍然可以再进行优化,就是这句:i=num/j;我们把它替换成i *= .1;为什么呢?因为在计算机内部,乘运算比除运算要快。让我们看一下测试结果吧:
1 2 3 4 5 6 7 8 9 | (左边是乘运算,右边是除运算,单位:毫秒) 当循环100万次时: 1028 1070 1049 1065 1045 1063 1024 1074 当循环1000万次时: 10319 10784 10467 10625 |
声明:以下文章是本人在学习过程中翻译的,如果需要复制,请务必注明出处:http://www.p-boy.cn
In this tutorial we will learn how to texture polygonal objects with Alternativa3D methods. We’ll allpy textures to a house built in previous tutorial, so if you didn’t complete it before, it is recommended to do that.
在这一节的向导中,我们将要学习如何利用Alternativa3D的方法建立多边形材质对象。我们要给上一节中的房子合成材质。因此,如果你之前还没有做完的话,建议你先将它完成。
Create new project named TexturingTutorial and place source code of lesson in it. Don’t forget to connect SWC-libraries from Alternativa3D package.
创建新项目,命名为TexturingTutorial并将源代码加入其中。不要忘记连接Alternativa3D包中的SWC库文件。
Project consists of three classes and two graphic files containing textures of bricks and roof tiling. We will use rectangular textures to reduce calculating a lil’bit. Main class, as usual, contains scene creation code and necessary event handlers. The only difference is in type of object being added, this time it is TexturedHouse class object. TexturedHouse class is a descendant of House class (created in a previous tutorial), and it redefine setMaterials() method.
项目中包含了3个类、两个包含砖和瓦盖材质的绘图文件,我们使用矩形材质来减少一些计算。通常,主类包含了建立场景的代码和必要的事件处理机制。这里唯一的区别是加入了对象类型,现在用到的是TexturedHouse类对象。TexturedHouse类是House的子类(在之前的教程中建立过),并且重新定义了setMaterials方法。
Materials and UV-coordinates——材质和UV坐标
Basic thing to get polygonal object draw in Alternativa3D is material. You can set material to every object’s surface, and one surface may contain only one material. In previous lessons we used alternativa.engine3d.materials.WireMaterial, which draws polygons’ edges. This time we’ll use with fill and texture materials.
在Alternativa3D中获得多边形对象绘制的基本对象是材质,你可以给任何对象表面设置材质,一个表面只能包含唯一的材质。在之前的教程中我们使用了alternativa.engine3d.materials.WireMaterial,它用来绘制多边形的边缘,这一次我们将填充纹理材质。
To be able for material to put texture on a face of 3D-object, it is necessary to set a way to find texture point corresponding given face point. It is achieved by setting texture coordinates for first three vertices, forming the face. Depending on given values, transformation matrix between texture plane and face plane is being formed.
为了能够把材质与3D对象纹理对应上,必须建立一种方式寻找纹理的点来符合面上的点,实现给前三个顶点设置纹理坐标来形成面。通过传值,当纹理平面和所建立的平面被创建之后,在两者之间使用matrix变形。
Coordinates in texture space are marked as U and V symbols, as a convention. Lower left texture corner has U = 0, V = 0 coordinates, upper right – U = 1, V = 1. You can see rectangular texture piece and triangle face projection to texture coordinates space, set by vertices a, b and c.
在纹理空间的坐标被U、V记号所标记,作为协议。左下角的坐标U = 0, V = 0,右上角U = 1, V = 1。你能看到给纹理坐标空间的矩形纹理和三角面投影,设为a、b、c顶点。

Texturing object——纹理对象
Let’s see how to set UV-coordinates for walls. Every wall is formed by one face. We have to set UV-coordinates for first three face’s vertices in order to apply texture. In our case they are lower-left, lower-right and upper-right wall points. Let’s agree that texture size is equal to wall size. Then, if we set wall height as H and it’s length as L, and take into account that corners’ coordinates vary from 0 to 1, and textures are rectangular, UV-coordinates of first three vertices will be (0, 0), (L/H, 0) and (L/H, 1) accordingly. Let’s take into account that walls standing along different axes will have different right side coordinates. As a result, we can prepare needed values:
我们看看如何给墙面设置UV坐标。每个墙由一个面所构建,我们必须设置UV坐标给前三个顶点来应用纹理。在我们的例子中他们是墙面的左下、右下和右上的点。我们需要纹理尺寸和墙面尺寸保持一致,然后,如果我们把墙的高度设为H、长度设为L,考虑角的坐标从0到1的改变,纹理是矩形的,前三个点的UV坐标则相应是(0, 0), (L/H, 0) 和(L/H, 1)。我们考虑墙沿着不同坐标矗立着,将会有不同的右侧坐标。因此,我们可以准备所需要的值:
1 2 3 4 5 | // Texture fills the wall by the height once——纹理填充墙的高度 var wallsReferenceHeight:Number = wallsHeight; // U-coordinates of right walls' sides. First coordinate is for northern and southern walls, second is for western and eastern ones //墙右侧的U坐标,第一个坐标是北墙和南墙,第二个是西墙和东墙。 var wallU:Array = [houseWidth / wallsReferenceHeight, houseLength / wallsReferenceHeight]; |
Next step is calculating UV-coordinates for roof faces. This will be slightly more difficult because of their trapezium shape. Let’s agree that texture heigth is equal to a roof slope height. So, defining slope height as H, lower slope length as bL and upper slope length as tL, UV coordinates of slope first three vertices will be (0, 0), (bL/H, 0) and ((bL + tL)/2H, 1) accordingly. It is necessary to adjust V-coordinate of the upper edge for western and eastern sides of the roof, by dividing eastern slope height by northern one.
下一步计算屋顶面的UV坐标。这会有点不同,因为他们是梯形。我们设定纹理高度等于屋顶斜坡高度,因此,定义斜坡高度为H,底部斜坡为bL,顶部斜坡为tL,前三个顶点的UV坐标点顺序就会是 (0, 0), (bL/H, 0) 和((bL + tL)/2H,1)。 有必要用东侧和西侧斜坡来划分西侧、东侧屋顶的上部边缘,调整他们的V坐标。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // Northern and southern roof slopes' height——北侧和南侧屋顶高度 var snSlopeHeight:Number = getHypotenuse(roofHeight, (roofBottomLength - roofTopLength) / 2); // Western and eastern roof slopes' height——西侧和东侧屋顶高度 var weSlopeHeight:Number = getHypotenuse(roofHeight, (roofBottomWidth - roofTopWidth) / 2); // Texture fills whole nortern or southern slope by height——纹理填充整个北侧和南侧的高度 var roofReferenceHeight:Number = snSlopeHeight; // U-coordinates of lower-right vertices of the roof slope. First coordinate is for northern and southern slope, second is for eastern and western one //屋顶斜坡的右下角的U坐标。第一个坐标是北侧和南侧的斜坡,第二个坐标是东侧和西侧的斜坡。 var roofBottomU:Array = [roofBottomWidth / roofReferenceHeight, roofBottomLength / roofReferenceHeight]; // U-coordinates for upper-right vertices of the roof slope. First coordinate is for northern and southern slope, second is for eastern and western one //屋顶斜坡的右上角的U坐标。第一个坐标是北侧和南侧的斜坡,第二个坐标是东侧和西侧的斜坡。 var roofTopU:Array = [0.5 * (roofBottomWidth + roofTopWidth) / roofReferenceHeight, 0.5 * (roofBottomLength + roofTopLength) / roofReferenceHeight]; // V-coordinates for upper vertices of the roof slope. First coordinate is for northern and southern slope, second is for eastern and western one //屋顶斜坡的上部的V坐标。第一个坐标是北侧和南侧的斜坡,第二个坐标是东侧和西侧的斜坡。 var roofTopV:Array = [1, weSlopeHeight / roofReferenceHeight]; |
Now, having all necessary coordinates calculated, we can set them to faces.
现在,所有必要的坐标都计算过了,我们可以设置他们的面了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // Running over plane XY quadrants, beginning from zero //运行XY象限,从0开始 for (var i:int = 0; i < 4; i++) { // wall mapping——墙面映射 // U-coordinate of wall right side——墙面右侧U坐标 var u:Number = wallU[i & 1]; setUVsToFace(new Point(0, 0), new Point(u, 0), new Point(u, 1), "wall_" + i); // roof slope mapping——屋顶斜坡映射 setUVsToFace(new Point(0, 0), new Point(roofBottomU[i & 1], 0), new Point(roofTopU[i & 1], roofTopV[i & 1]), "roof_slope_" + i); } // upper roof side mapping——屋顶上部映射 setUVsToFace(new Point(0, 0), new Point(roofTopLength / roofReferenceHeight, 0), new Point(roofTopLength / roofReferenceHeight, roofTopWidth / roofReferenceHeight), "roof_top"); |
After setting texture coordinates we have to set texture materials to according surfaces. While creating texture material, it is necessary to define alternativa.types.Texture class instance, which is used for filling. Texture has to have graphics set, which is being get from project files in our case:
设置完纹理坐标之后我们必须根据表面设置纹理材质,在创建纹理材质时,必须定义alternativa.types.Texture类,用于填充。纹理必须拥有图形设置,可以从我们例子的项目文件中获得:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | [Embed(source="resources/wall.jpg")] private static const bmpWall:Class; [Embed(source="resources/roof.jpg")] private static const bmpRoof:Class; private static const wallTexture:Texture = new Texture(new bmpWall().bitmapData, "wall"); private static const roofTexture:Texture = new Texture(new bmpRoof().bitmapData, "roof"); //... // Set solid fill for lower roof parts and house box //为屋顶底部和房子体设置固定填充 setMaterialToSurface(new FillMaterial(0x666666), "roof_bottom"); setMaterialToSurface(new FillMaterial(0x666666), "box_bottom"); // Set texture materials for roof and walls //为屋顶和墙面设置纹理材质 setMaterialToSurface(new TextureMaterial(wallTexture), "walls"); setMaterialToSurface(new TextureMaterial(roofTexture), "roof"); |
We get this house as a result.
我们得到了这所房子了。