15 重构太阳系(2)

在《重构太阳系(1)》中,我们将太阳、水星、地球和月球从SunSys分离出来单独成类。并了解了组合的关系。但是我们忽略了3个容器与水星、地球、月亮的关系。我们通过下图可以清楚地明白SunSys中所有类的关系。


       SunSys由Sun、WaterContainer和EarthContainer三个部分构成。WaterContainer由Water构成。EarthContain由Earth、MoonContainer两个部分构成。MoonContainer由Moon构成。

       依据上面的分析,继续重构SunSys项目。将WaterContainer、EarthContainer和MoonContainer编写成单独的类。

WaterContainer.as

package  
{
	import org.papervision3d.objects.DisplayObject3D;
	import org.papervision3d.objects.primitives.Sphere;
	/**
	 * ...
	 * @author hellopv3d
	 */
	public class WaterContainer extends DisplayObject3D 
	{
		private var water:Sphere;
		
		public function WaterContainer() 
		{
			water = new Water();
			this.addChild(water);
			
		}
		
	}

}

MoonContainer.as

package  
{
	import org.papervision3d.objects.DisplayObject3D;
	import org.papervision3d.objects.primitives.Sphere;
	/**
	 * ...
	 * @author hellopv3d
	 */
	public class MoonContainer extends DisplayObject3D
	{
		private var moon:Sphere;
		
		public function MoonContainer() 
		{
			moon = new Moon();
			this.addChild(moon);

		}
		
	}

}

EarthContainer.as

package  
{
	import org.papervision3d.objects.DisplayObject3D;
	import org.papervision3d.objects.primitives.Sphere;
	/**
	 * ...
	 * @author hellopv3d
	 */
	public class EarthContainer extends DisplayObject3D
	{
		private var earth:Sphere;
		private var moonContainer:MoonContainer;
		
		public function EarthContainer() 
		{
			earth = new Earth();
			this.addChild(earth);
			
			moonContainer = new MoonContainer();
			this.addChild(moonContainer);
			
			moonContainer.position = earth.position;
			
		}
		
	}

}


SunSys.as

package  
{
	import flash.events.Event;
	import mx.core.BitmapAsset;
	import org.papervision3d.core.geom.Particles;
	import org.papervision3d.core.geom.renderables.Particle;
	import org.papervision3d.materials.BitmapMaterial;
	import org.papervision3d.materials.special.ParticleMaterial;
	import org.papervision3d.objects.DisplayObject3D;
	import org.papervision3d.objects.primitives.Sphere;
	import org.papervision3d.view.BasicView;
	/**
	 * ...
	 * @author hellopv3d
	 */
	//[SWF(width = "1024", height = "800", backgroundColor = "0x000000")]
	public class SunSys extends BasicView
	{
		private var sun:Sphere;
		
		private var waterContain:WaterContainer;
		private var earthContain:EarthContainer;
		
		public function SunSys() 
		{
			
			initContain();//初始化容器
			init3DObjects();//初始化3D对象
			//调整摄像机
			camera.y = 500;
			camera.z = -2000;
			
			startRendering();
			
		}
		
		private function initContain():void {
			
			waterContain = new WaterContainer();
			scene.addChild(waterContain);
			
			//创建容器
			earthContain = new EarthContainer();
			scene.addChild(earthContain);
		}
		
		private function init3DObjects():void {
			createSun();
		}
		
		private function createSun():void {
			//创建太阳
			sun = new Sun();
			scene.addChild(sun);
		}
		
		override protected function onRenderTick(e:Event = null):void {
			super.onRenderTick();
			
			waterContain.rotationY += 3;
			earthContain.rotationY++;

		}
		
	}

}

重构后的类图如下所示。


       从SunSys代码可以看到,SunSys类属性只有sun、waterContain和earthContainer。我们在文档类中只关注这三个类的实例化,Water、Earth、MoonContainer和Moon都被封装起来了,当然也没有必要去理会了。

       测试运行,发现缺少了地球自转和月球绕地球转动。因为在文档类属性中没有定义Earth对象和MoonContainer对象,因此,不能在刷屏方法onRenderTick中使用。我们将earth组合进earthContainer中,隐藏了earth类。只要我们在EarthContainer类中编写获取earth对象的方法即可解决这个问题。如下代码所示。

EarthContainer.as

package  
{
	……
		public function getEarth():Sphere {
			return earth;
		}
		
		public function getMoonContainer():MoonContainer {
			return moonContainer;
		}
		
	……

}

SunSys.as

package  
{
	……
		override protected function onRenderTick(e:Event = null):void {
			super.onRenderTick();
			
			waterContain.rotationY += 3;
			earthContain.rotationY++;
			//earth.localRotationY += 3;
			earthContain.getEarth().rotationY += 3;
			
			//moonContain.localRotationY += 15;
			earthContain.getMoonContainer().localRotationY += 15;
		}
		
	……

}

但是这样和面向对象思想冲突,将地球自己的事情(自转)交给了文档类实现。有没有什么好的办法来处理这个问题呢?有的,不过要请来哈希表。

在运用哈希表之前,我们可以进一步重构,将SunSys做成一个单独的类,而不是文档类。这样我们就可以在文档类中直接生成Sunsys实例,对于其他的类,我们就没有必要去理会了。

SunSys.as

package  
{

	import org.papervision3d.objects.DisplayObject3D;
	/**
	 * ...
	 * @author yl
	 */

	public class SunSys extends DisplayObject3D
	{
		private var sun:Sun;		
		private var earthContain:EarthContainer;
		private var waterContain:WaterContainer;
		
		public function SunSys() 
		{
			
			initContainer();//创建容器
			init3DObjects();//创建3D物体			
		
		}
		
		private function init3DObjects():void {
			createSun();
			createSpace();
		}
		
		private function createSpace():void {
			//创建粒子容器,并加入场景显示
			var particles:Space = new Space();
			this.addChild(particles);
		}
		
		private function createSun():void {
			//创建太阳
			sun = new Sun();
			this.addChild(sun);
		}
		
		private function initContainer():void {
			//创建水星容器
			waterContain = new WaterContainer();
			this.addChild(waterContain);
			
			//创建地球容器
			earthContain = new EarthContainer();
			this.addChild(earthContain);			
		}

	}
}
SunSysTest.as

package  
{
	import flash.events.Event;
	import org.papervision3d.view.BasicView;
	/**
	 * ...
	 * @author yl
	 */
	public class SunSysTest extends BasicView 
	{
		
		private var sunSys:SunSys;
		
		public function SunSysTest() 
		{
			
			sunSys = new SunSys();
			scene.addChild(sunSys);
			
			
			camera.z = -2000;
			camera.y = 1000;
                 
                	startRendering();
		}
		
		override protected function onRenderTick(e:Event = null):void {
			super.onRenderTick();

		}
	}

}

由于文档类除了SunSys类属性外没有任何属性,因此不能在刷屏方法中进行相关的转动。

解决方法是给需要的类提供public接口,返回自身即可。具体代码可通过下面链接下载:

http://download.csdn.net/detail/gdhyyanglang/4181810


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值